I always see a lot of examples where virtual functions are declared as protected in header files. Is it wrong to declare virtual functions as public? What is the best practice when using virtual functions?
Is it wrong to declare virtual functions as public?
No.
What is the best practice when using virtual functions?
That completely depends on your use cases. The keywords per se are orthogonal in usage.
Sometimes it's good to have protected virtual functions like with the template design pattern, most of the time the virtual functions are declared public to provide an interface.
There are two design pattern categories the public and protected inheritance fall into:
Template function pattern:
class Base {
public:
void foo() {
bar();
};
protected:
virtual void bar() = 0;
};
class Implementation : public Base {
void bar() {
// provide the implementation
}
};
Interface pattern:
struct Interface {
virtual void foo() = 0;
virtual ~Interface() {}
};
class Implementation : public Interface {
public:
void foo() {
// provide the implementation
}
};
There are other design patterns, that may omit virtual at all (see CTRP), but the semantics of public and protected are still kept.
Related
Consider the following program
class Node {
public:
virtual void Visit() = 0;
};
class Graph {
public:
virtual void Visit();
};
class GraphNode1 : public Node, Graph {
};
class GraphNode2 : public Node, Graph {
using Graph::Visit;
};
class GraphNode3 : public Node, Graph {
public:
virtual void Visit() {
Graph::Visit();
}
};
int main()
{
GraphNode1 a;
GraphNode2 b;
GraphNode3 c;
}
It does not compile, but complains that GraphNode1 and GraphNode2 are abstract, since Node::Visit is pure virtual.
I would have assumed that both GraphNode1 and GraphNode2 were fine, since:
They contain an implementation of Visit.
They contain only a single implementation of Visit, so there should be no ambiguity.
Can anyone explain why I have to create an explicit implementation to make it work.
Node and Graph are unrelated classes. Which makes Node::Visit and Graph::Visit distinct unrelated member functions.
Neither can override the other. You seem to think Graph::Visit is somehow "better" than Node::Visit on account of not being pure virtual, and should therefore override it. But there is no objective reason for it. For starters, pure virtual functions can have a definition:
struct A {
virtual void thing() = 0;
};
inline void A::thing() {}
And secondly, a function can be made pure virtual when overriden:
struct A {
virtual void thing() {}
};
struct B : A {
void thing() override = 0;
};
So really, there is no reason for Node::Visit and Graph::Visit to interact as overriders of each other. That's why you need to be explicit and define a function yourslef that will serve as an overrider*.
* One shortcoming of C++ is that you in fact override both Node::Visit and Graph::Visit in GraphNode3. IMO it's a quirk of the language (really, it should be possible to keep them unrelated). MSVC has an extension that lets you choose what to override in a more fine-grained manner.
I just find out that overriding a private function to a public one from base object is allowed in C++ since Visual Studio produces 0 warning. Is there any potential danger to doing that?
If there isn't, what's the difference between declaring a virtual function in private, protected and public in a base object?
what's the difference between declaring a virtual function in
private, protected and public in a base object?
The difference is that a private virtual function can be called only from a base class. This can be useful if the function is not a part of an external class interface, and is only used by base class. So that users call (some other) base class' member, and that member calls the virtual function. For example:
class Base {
virtual void stage1()=0; // derived classes override this
virtual void stage2()=0;
public:
void run() { stage1(); stage2(); } // users call this
};
Moreover, there is a point of view that you should not make your virtual functions public at all, because the fact that they are virtual is internals of the class and its subclasses, and the users should not be aware of that. It is rarely that the same function must be overridden and callable from external code. This allows the base class to control which (virtual) functions can be called from which (non-virtual) public method, making maiteinance easier.
See more details in this article by Herb Sutter:
...each [public] virtual
function is doing two jobs: It's specifying interface because it's
public...; and it's specifying implementation detail,
namely the internally customizable behavior... That a public virtual
function inherently has two significantly different jobs is a sign
that it's not separating concerns well and that we should consider a
different approach. What if we want to separate the specification of
interface from the specification of the implementation's customizable
behavior?
...
In summary, prefer to make base class virtual functions private (or
protected if you really must). This separates the concerns of
interface and implementation, which stabilizes interfaces and makes
implementation decisions easier to change and refactor later.
However, I am not qualified to say whether this is really widely used...
Is there any potential danger to doing that?
I don't think so, because you are still very limited:
class Base
{
private:
virtual void foo(){}
};
class Derived1 : public Base
{
public:
virtual void foo(){ Base::foo(); }
};
class Derived2 : public Base
{
public:
virtual void foo(){}
};
int main()
{
Derived1 d1;
d1.foo(); //error
Base * d2 = new Derived2();
d2->foo(); //error
}
So at best you will be able to call the overloaded function (if it doesn't call the function from the base class from itself), but the function of the base class will still have the same visibility, and will be inaccessible.
When changing access visibility by overriding in derived class, base class visibility doesn't change:
So with:
class Base {
public:
virtual ~Base() = default;
protected:
virtual void foo() = 0;
};
class Derived : public Base {
public:
void foo() override {};
};
Then
Derived d;
Base& b = d;
d.foo(); // valid
b.foo(); // invalid
If there isn't, what's the difference between declaring a virtual function in private, protected and public in a base object?
It depends on how you access the function. The type of the object/pointer you use determines whether you can access the function.
class Base
{
public:
virtual void foo() {}
};
class Derived : public Base
{
private:
virtual void foo() {}
};
int main()
{
Derived* dptr = new Derived;
Base* bptr = dptr;
dptr->foo(); // Can't use it. Derived::foo is private
bptr->foo(); // Can use it. Base::foo is public.
}
Compiler message, using g++ 4.9.3.
socc.cc: In function ‘int main()’:
socc.cc:12:20: error: ‘virtual void Derived::foo()’ is private
virtual void foo() {}
^
socc.cc:20:14: error: within this context
dptr->foo(); // Can't use it. Derived::foo is private
A virtual function is a customization point for derived class implementations. If it is private then it's purely an implementation detail. Making it more accessible in a derived class then exposes an implementation detail, with all that that entails. In particular client code can come to depend on that detail so that the implementation can't be easily changed. It can also be easier for client tode to call in incorrect ways, than the originally intended interface, and it can yield results that are only valid in certain contexts, so that it's more brittle than the original interface.
The following code:
struct interface_base
{
virtual void foo() = 0;
};
struct interface : public interface_base
{
virtual void bar() = 0;
};
struct implementation_base : public interface_base
{
void foo();
};
struct implementation : public implementation_base, public interface
{
void bar();
};
int main()
{
implementation x;
}
fails to compile with the following errors:
test.cpp: In function 'int main()':
test.cpp:23:20: error: cannot declare variable 'x' to be of abstract type 'implementation'
test.cpp:16:8: note: because the following virtual functions are pure within 'implementation':
test.cpp:3:18: note: virtual void interface_base::foo()
I have played around with it and figured out that making the 'interface -> interface_base' and 'implementation_base -> interface_base' inheritances virtual, fixes the problem, but I don't understand why. Can someone please explain what is going on?
p.s. I omitted the virtual destructors on purpose to make the code shorter. Please don't tell me to put them in, I already know :)
You have two interface_base base classes in your inheritance tree. This means you must provide two implementations of foo(). And calling either of them will be really awkward, requiring multiple casts to disambiguate. This usually is not what you want.
To resolve this, use virtual inheritance:
struct interface_base
{
virtual void foo() = 0;
};
struct interface : virtual public interface_base
{
virtual void bar() = 0;
};
struct implementation_base : virtual public interface_base
{
void foo();
};
struct implementation : public implementation_base, virtual public interface
{
void bar();
};
int main()
{
implementation x;
}
With virtual inheritance, only one instance of the base class in question is created in the inheritance heirarchy for all virtual mentions. Thus, there's only one foo(), which can be satisfied by implementation_base::foo().
For more information, see this prior question - the answers provide some nice diagrams to make this all more clear.
The usual C++ idiom is:
public virtual inheritance for interface classes
private non-virtual inheritance for implementation classes
In this case we would have:
struct interface_base
{
virtual void foo() = 0;
};
struct interface : virtual public interface_base
{
virtual void bar() = 0;
};
struct implementation_base : virtual public interface_base
{
void foo();
};
struct implementation : private implementation_base,
virtual public interface
{
void bar();
};
In implementation, the unique interface_base virtual base is :
publicly inherited via interface: implementation --public--> interface --public--> interface_base
privately inherited via implementation_base: implementation --private--> implementation_base --public--> interface_base
When client code does one of these derived to base conversions:
derived to base pointer conversions,
reference binding of base type with an initializer of static type derived,
access to inherited base class members via a lvalue of derived static type,
what matters is only that there is a least one accessible inheritance path from the derived class to the given base class subobject; other inaccessible paths are simply ignored. Because inheritance of the base class is only virtual here, there is only one base class subject so these conversions are never ambiguous.
Here, the conversion from implementation to interface_base, can always be done by client code via interface; the other inaccessible path does not matter at all. The unique interface_base virtual base is publicly inherited from implementation.
In many cases, the implementation classes (implementation, implementation_base) will be kept hidden from client code: only pointers or references to the interface classes (interface, interface_base) will be exposed.
For the case of 'solving' the diamond inheritance problem, the solutions offered by bdonlan are valid. Having said that, you can avoid the diamond-problem with design. Why must every instance of a given class be seen as both classes? Are you ever going to pass this same object to a class that says something like:
void ConsumeFood(Food *food);
void ConsumeDrink(Drink *drink);
class NutritionalConsumable {
float calories() = 0;
float GetNutritionalValue(NUTRITION_ID nutrition) = 0;
};
class Drink : public NutritionalConsumable {
void Sip() = 0;
};
class Food : public NutritionalConsumable {
void Chew() = 0;
};
class Icecream : public Drink, virtual public Food {};
void ConsumeNutrition(NutritionalConsumable *consumable) {
ConsumeFood(dynamic_cast<Food*>(food));
ConsumeDrink(dynamic_cast<Drink*>(drink));
}
// Or moreso
void ConsumeIcecream(Icecream *icecream) {
ConsumeDrink(icecream);
ConsumeFood(icecream);
}
Surely it would be better in this case for Icecream to just implement NutritionalConsumable and provide a GetAsDrink() and GetAsFood() method that will return a proxy, purely for the sake of appearing as either food or drink. Otherwise that suggests that there is a method or object that accepts a Food but somehow wants to later see it as a Drink, which can only be achieved with a dynamic_cast, and needn't be the case with a more appropriate design.
I have the following hierarchy of classes
class classOne
{
virtual void abstractMethod() = 0;
};
class classTwo : public classOne
{
};
class classThree : public classTwo
{
};
All classOne, classTwo and classThree are abstract classes, and I have another class that is defining the pure virtual methods
class classNonAbstract : public classThree
{
void abstractMethod();
// Couple of new methods
void doIt();
void doItToo();
};
And right now I need it differently...I need it like
class classNonAbstractOne : public classOne
{
void abstractMethod();
// Couple of new methods
void doIt();
void doItToo();
};
class classNonAbstractTwo : public classTwo
{
void abstractMethod();
// Couple of new methods
void doIt();
void doItToo();
};
and
class classNonAbstractThree : public classThree
{
void abstractMethod();
// Couple of new methods
void doIt();
void doItToo();
};
But all the nonAbstract classes have the same new methods, with the same code...and I would like to avoid copying all the methods and it's code to every nonAbstract class. How could I accomplish that?
Hopefully it's understandable...
template<class Base>
struct Concrete : Base {
void abstractMethod();
void doIt() {
// example of accessing inherited members:
int n = Base::data_member; // or this->data_member
n = Base::method(); // non-virtual dispatch
n = this->method(); // virtual dispatch
// since Base is a template parameter, 'data_member' and 'method' are
// dependent names and using them unqualified will not properly find
// them
}
void doItToo();
};
typedef Concrete<classOne> classNonAbstractOne; // if desired, for convenience
Make sure to give your abstract base classes either a virtual public destructor or make the destructor protected (then it doesn't have to be virtual, but still can be).
Because the template must be parsed with names looked up without yet knowing exactly what Base will be, you need to either use Base::member or this->member to access inherited members.
I usually try to avoid inheritance if possible (except for pure abstract classes which define pure interfaces) because it creates a tight coupling. In many cases composition is the better alternative.
Also, things tend to get messy with complex inheritance structures. It's not easy to say from your description what's the best in this particular case. Just pointing this out as a rule of thumb.
In C++ an interface can be implemented by a class whose methods are pure virtual.
Such a class could be part of a library to describe what methods an object should implement to be able to work with other classes in the library:
class Lib::IFoo
{
public:
virtual void method() = 0;
};
:
class Lib::Bar
{
public:
void stuff( Lib::IFoo & );
};
Now I want to to use class Lib::Bar, so I have to implement the IFoo interface.
For my purposes I need a whole of related classes so I would like to work with a base class that guarantees common behavior using the NVI idiom:
class FooBase : public IFoo // implement interface IFoo
{
public:
void method(); // calls methodImpl;
private:
virtual void methodImpl();
};
The non-virtual interface (NVI) idiom ought to deny derived classes the possibility of overriding the common behavior implemented in FooBase::method(), but since IFoo made it virtual it seems that all derived classes have the opportunity to override the FooBase::method().
If I want to use the NVI idiom, what are my options other than the pImpl idiom already suggested (thanks space-c0wb0y).
I think you've got your NVI pattern around the wrong way:
http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface
Not sure if that solves your issue though.
class IFoo
{
public:
void method() { methodImpl(); }
private:
virtual void methodImpl()=0;
};
class FooBase : public IFoo // implement interface IFoo
{
private:
virtual void methodImpl();
};
Here's an example of why you might do this using a reader that reads from XML and another from DB. Note that common structure is moved into the NVI readFromSource, while non-common behaviour is moved into the private virtual getRawDatum. This way logging and error checking is only needed in the one function.
class IReader
{
public:
// NVI
Datum readFromSource()
{
Datum datum = getRawDatum();
if( ! datum.isValid() ) throw ReaderError("Unable to get valid datum");
logger::log("Datum Read");
return datum;
}
private:
// Virtual Bits
Datum getRawDatum()=0;
};
class DBReader : public IReader
{
private:
Datum getRawDatum() { ... }
};
class XmlReader : public IReader
{
private:
Datum getRawDatum() { ... }
};
Commonly, the reason for using the NVI (sometimes also called "Template Method") is that derived classes should only change a part of the base class' behavior. So what you do is this:
class base {
public:
void f()
{
// do something derived classes shouldn't interfere with
vf();
// do something derived classes shouldn't interfere with
vg();
// do something derived classes shouldn't interfere with
vh();
// do something derived classes shouldn't interfere with
}
private:
virtual void vf(); // might be pure virtual, too
virtual void vg(); // might be pure virtual, too
virtual void vh(); // might be pure virtual, too
};
Derived classes can then plug into f() at the spots they are meant to and change aspects of f()'s behavior, without messing up its fundamental algorithm.
It may be confusing that once a method is declared as virtual in a base class, it automatically becomes virtual in all derived classes, even if the virtual keywords is not used there. So in your example, both methods of FooBase are virtual.
... to deny derived classes the
possibility of overriding the common
behavior implemented in
FooBase::method()...
If you can get rid of IFoo, and just start the hierarchy with FooBase with a non-virtual method, that would do it. But it looks like you want to allow direct children of IFoo to override method(), but to prevent children of FooBase to override it. I don't think that's possible.
You could use the pimpl-idiom to achieve this:
class IFoo
{
public:
IFoo( boost::shared_ptr< IFooImpl > pImpl )
: m_pImpl( pImpl )
{}
void method() { m_pImpl->method(); }
void otherMethod() { m_pImpl->otherMethod(); }
private:
boost::shared_ptr< IFooImpl > m_pImpl;
};
class IFooImpl
{
public:
void method();
virtual void otherMethod();
};
Now others can still subclass IFooImpl and pass it to IFoo, but they cannot override the behavior of method (they can override otherMethod). You can even make IFooImpl a direct subclass of IFoo and use enable_shared_from_this to initialize IFoo correctly. This is just the gist of the method. There are many ways to tweak this approach. For instance you can use the factory-pattern to make sure IFoos are created correctly.
Hope that helps.