I understand the need for a virtual destructor. But why do we need a pure virtual destructor? In one of the C++ articles, the author has mentioned that we use pure virtual destructor when we want to make a class abstract.
But we can make a class abstract by making any of the member functions as pure virtual.
So my questions are
When do we really make a destructor pure virtual? Can anybody give a good real time example?
When we are creating abstract classes is it a good practice to make the destructor also pure virtual? If yes..then why?
Probably the real reason that pure virtual destructors are allowed is that to prohibit them would mean adding another rule to the language and there's no need for this rule since no ill-effects can come from allowing a pure virtual destructor.
Nope, plain old virtual is enough.
If you create an object with default implementations for its virtual methods and want to make it abstract without forcing anyone to override any specific method, you can make the destructor pure virtual. I don't see much point in it but it's possible.
Note that since the compiler will generate an implicit destructor for derived classes, if the class's author does not do so, any derived classes will not be abstract. Therefore having the pure virtual destructor in the base class will not make any difference for the derived classes. It will only make the base class abstract (thanks for #kappa's comment).
One may also assume that every deriving class would probably need to have specific clean-up code and use the pure virtual destructor as a reminder to write one but this seems contrived (and unenforced).
Note: The destructor is the only method that even if it is pure virtual has to have an implementation in order to instantiate derived classes (yes pure virtual functions can have implementations, being pure virtual means derived classes must override this method, this is orthogonal to having an implementation).
struct foo {
virtual void bar() = 0;
};
void foo::bar() { /* default implementation */ }
class foof : public foo {
void bar() { foo::bar(); } // have to explicitly call default implementation.
};
All you need for an abstract class is at least one pure virtual function. Any function will do; but as it happens, the destructor is something that any class will have—so it's always there as a candidate. Furthermore, making the destructor pure virtual (as opposed to just virtual) has no behavioral side effects other than to make the class abstract. As such, a lot of style guides recommend that the pure virtual destuctor be used consistently to indicate that a class is abstract—if for no other reason than it provides a consistent place someone reading the code can look to see if the class is abstract.
If you want to create an abstract base class:
that can't be instantiated (yep, this is redundant with the term "abstract"!)
but needs virtual destructor behavior (you intend to carry around pointers to the ABC rather than pointers to the derived types, and delete through them)
but does not need any other virtual dispatch behavior for other methods (maybe there are no other methods? consider a simple protected "resource" container that needs a constructors/destructor/assignment but not much else)
...it's easiest to make the class abstract by making the destructor pure virtual and providing a definition (method body) for it.
For our hypothetical ABC:
You guarantee that it cannot be instantiated (even internal to the class itself, this is why private constructors may not be enough), you get the virtual behavior you want for the destructor, and you do not have to find and tag another method that doesn't need virtual dispatch as "virtual".
Here I want to tell when we need virtual destructor and when we need pure virtual destructor
class Base
{
public:
Base();
virtual ~Base() = 0; // Pure virtual, now no one can create the Base Object directly
};
Base::Base() { cout << "Base Constructor" << endl; }
Base::~Base() { cout << "Base Destructor" << endl; }
class Derived : public Base
{
public:
Derived();
~Derived();
};
Derived::Derived() { cout << "Derived Constructor" << endl; }
Derived::~Derived() { cout << "Derived Destructor" << endl; }
int _tmain(int argc, _TCHAR* argv[])
{
Base* pBase = new Derived();
delete pBase;
Base* pBase2 = new Base(); // Error 1 error C2259: 'Base' : cannot instantiate abstract class
}
When you want that no one should be able to create the object of Base class directly, use pure virtual destructor virtual ~Base() = 0. Usually at-least one pure virtual function is required, let's take virtual ~Base() = 0, as this function.
When you do not need above thing, only you need the safe destruction of Derived class object
Base* pBase = new Derived();
delete pBase;
pure virtual destructor is not required, only virtual destructor will do the job.
From the answers I have read to your question, I couldn't deduce a good reason to actually use a pure virtual destructor. For example, the following reason doesn't convince me at all:
Probably the real reason that pure virtual destructors are allowed is that to prohibit them would mean adding another rule to the language and there's no need for this rule since no ill-effects can come from allowing a pure virtual destructor.
In my opinion, pure virtual destructors can be useful. For example, assume you have two classes myClassA and myClassB in your code, and that myClassB inherits from myClassA. For the reasons mentioned by Scott Meyers in his book "More Effective C++", Item 33 "Making non-leaf classes abstract", it is better practice to actually create an abstract class myAbstractClass from which myClassA and myClassB inherit. This provides better abstraction and prevents some problems arising with, for example, object copies.
In the abstraction process (of creating class myAbstractClass), it can be that no method of myClassA or myClassB is a good candidate for being a pure virtual method (which is a prerequisite for myAbstractClass to be abstract). In this case, you define the abstract class's destructor pure virtual.
Hereafter a concrete example from some code I have myself written. I have two classes, Numerics/PhysicsParams which share common properties. I therefore let them inherit from the abstract class IParams. In this case, I had absolutely no method at hand that could be purely virtual. The setParameter method, for example, must have the same body for every subclass. The only choice that I have had was to make IParams' destructor pure virtual.
struct IParams
{
IParams(const ModelConfiguration& aModelConf);
virtual ~IParams() = 0;
void setParameter(const N_Configuration::Parameter& aParam);
std::map<std::string, std::string> m_Parameters;
};
struct NumericsParams : IParams
{
NumericsParams(const ModelConfiguration& aNumericsConf);
virtual ~NumericsParams();
double dt() const;
double ti() const;
double tf() const;
};
struct PhysicsParams : IParams
{
PhysicsParams(const N_Configuration::ModelConfiguration& aPhysicsConf);
virtual ~PhysicsParams();
double g() const;
double rho_i() const;
double rho_w() const;
};
If you want to stop instantiating of base class without making any change in your already implemented and tested derive class, you implement a pure virtual destructor in your base class.
You are getting into hypotheticals with these answers, so I will try to make a simpler, more down to earth explanation for clarity's sake.
The basic relationships of object oriented design are two:
IS-A and HAS-A. I did not make those up. That is what they are called.
IS-A indicates that a particular object identifies as being of the class that is above it in a class hierarchy. A banana object is a fruit object if it is a subclass of the fruit class. This means that anywhere a fruit class can be used, a banana can be used. It is not reflexive , though. You can not substitute a base class for a specific class if that specific class is called for.
Has-a indicated that an object is part of a composite class and that there is an ownership relationship. It means in C++ that it is a member object and as such the onus is on the owning class to dispose of it or hand ownership off before destructing itself.
These two concepts are easier to realize in single-inheritance languages than in a multiple inheritance model like c++, but the rules are essentially the same. The complication comes when the class identity is ambiguous, such as passing a Banana class pointer into a function that takes a Fruit class pointer.
Virtual functions are, firstly, a run-time thing. It is part of polymorphism in that it is used to decide which function to run at the time it is called in the running program.
The virtual keyword is a compiler directive to bind functions in a certain order if there is ambiguity about the class identity. Virtual functions are always in parent classes (as far as I know) and indicate to the compiler that binding of member functions to their names should take place with the subclass function first and the parent class function after.
A Fruit class could have a virtual function color() that returns "NONE" by default.
The Banana class color() function returns "YELLOW" or "BROWN".
But if the function taking a Fruit pointer calls color() on the Banana class sent to it -- which color() function gets invoked?
The function would normally call Fruit::color() for a Fruit object.
That would 99% of the time not be what was intended.
But if Fruit::color() was declared virtual then Banana:color() would be called for the object because the correct color() function would be bound to the Fruit pointer at the time of the call.
The runtime will check what object the pointer points to because it was marked virtual in the Fruit class definition.
This is different than overriding a function in a subclass. In that case
the Fruit pointer will call Fruit::color() if all it knows is that it IS-A pointer to Fruit.
So now to the idea of a "pure virtual function" comes up.
It is a rather unfortunate phrase as purity has nothing to do with it. It means that it is intended that the base class method is never to be called.
Indeed a pure virtual function can not be called. It must still be defined, however. A function signature must exist. Many coders make an empty implementation {} for completeness, but the compiler will generate one internally if not. In that case when the function is called even if the pointer is to Fruit , Banana::color() will be called as it is the only implementation of color() there is.
Now the final piece of the puzzle: constructors and destructors.
Pure virtual constructors are illegal, completely. That is just out.
But pure virtual destructors do work in the case that you want to forbid the creation of a base class instance. Only sub classes can be instantiated if the destructor of the base class is pure virtual.
the convention is to assign it to 0.
virtual ~Fruit() = 0; // pure virtual
Fruit::~Fruit(){} // destructor implementation
You do have to create an implementation in this case. The compiler knows this is what you are doing and makes sure you do it right, or it complains mightily that it can not link to all the functions it needs to compile. The errors can be confusing if you are not on the right track as to how you are modeling your class hierarchy.
So you are forbidden in this case to create instances of Fruit, but allowed to create instances of Banana.
A call to delete of the Fruit pointer that points to an instance of Banana
will call Banana::~Banana() first and then call Fuit::~Fruit(), always.
Because no matter what, when you call a subclass destructor, the base class destructor must follow.
Is it a bad model? It is more complicated in the design phase, yes, but it can ensure that correct linking is performed at run-time and that a subclass function is performed where there is ambiguity as to exactly which subclass is being accessed.
If you write C++ so that you only pass around exact class pointers with no generic nor ambiguous pointers, then virtual functions are not really needed.
But if you require run-time flexibility of types (as in Apple Banana Orange ==> Fruit ) functions become easier and more versatile with less redundant code.
You no longer have to write a function for each type of fruit, and you know that every fruit will respond to color() with its own correct function.
I hope this long-winded explanation solidifies the concept rather than confuses things. There are a lot of good examples out there to look at,
and look at enough and actually run them and mess with them and you will get it.
You asked for an example, and I believe the following provides a reason for a pure virtual destructor. I look forward to replies as to whether this is a good reason...
I do not want anyone to be able to throw the error_base type, but the exception types error_oh_shucks and error_oh_blast have identical functionality and I don't want to write it twice. The pImpl complexity is necessary to avoid exposing std::string to my clients, and the use of std::auto_ptr necessitates the copy constructor.
The public header contains the exception specifications that will be available to the client to distinguish different types of exception being thrown by my library:
// error.h
#include <exception>
#include <memory>
class exception_string;
class error_base : public std::exception {
public:
error_base(const char* error_message);
error_base(const error_base& other);
virtual ~error_base() = 0; // Not directly usable
virtual const char* what() const;
private:
std::auto_ptr<exception_string> error_message_;
};
template<class error_type>
class error : public error_base {
public:
error(const char* error_message) : error_base(error_message) {}
error(const error& other) : error_base(other) {}
~error() {}
};
// Neither should these classes be usable
class error_oh_shucks { virtual ~error_oh_shucks() = 0; }
class error_oh_blast { virtual ~error_oh_blast() = 0; }
And here is the shared implementation:
// error.cpp
#include "error.h"
#include "exception_string.h"
error_base::error_base(const char* error_message)
: error_message_(new exception_string(error_message)) {}
error_base::error_base(const error_base& other)
: error_message_(new exception_string(other.error_message_->get())) {}
error_base::~error_base() {}
const char* error_base::what() const {
return error_message_->get();
}
The exception_string class, kept private, hides std::string from my public interface:
// exception_string.h
#include <string>
class exception_string {
public:
exception_string(const char* message) : message_(message) {}
const char* get() const { return message_.c_str(); }
private:
std::string message_;
};
My code then throws an error as:
#include "error.h"
throw error<error_oh_shucks>("That didn't work");
The use of a template for error is a little gratuitous. It saves a bit of code at the expense of requiring clients to catch errors as:
// client.cpp
#include <error.h>
try {
} catch (const error<error_oh_shucks>&) {
} catch (const error<error_oh_blast>&) {
}
Maybe there is another REAL USE-CASE of pure virtual destructor which I actually can't see in other answers :)
At first, I completely agree with marked answer: It is because forbidding pure virtual destructor would need an extra rule in language specification. But it's still not the use case that Mark is calling for :)
First imagine this:
class Printable {
virtual void print() const = 0;
// virtual destructor should be here, but not to confuse with another problem
};
and something like:
class Printer {
void queDocument(unique_ptr<Printable> doc);
void printAll();
};
Simply - we have interface Printable and some "container" holding anything with this interface. I think here it is quite clear why print() method is pure virtual. It could have some body but in case there is no default implementation, pure virtual is an ideal "implementation" (="must be provided by a descendant class").
And now imagine exactly the same except it is not for printing but for destruction:
class Destroyable {
virtual ~Destroyable() = 0;
};
And also there could be a similar container:
class PostponedDestructor {
// Queues an object to be destroyed later.
void queObjectForDestruction(unique_ptr<Destroyable> obj);
// Destroys all already queued objects.
void destroyAll();
};
It's simplified use-case from my real application. The only difference here is that "special" method (destructor) was used instead of "normal" print(). But the reason why it is pure virtual is still the same - there is no default code for the method.
A bit confusing could be the fact that there MUST be some destructor effectively and compiler actually generates an empty code for it. But from the perspective of a programmer pure virtuality still means: "I don't have any default code, it must be provided by derived classes."
I think it's no any big idea here, just more explanation that pure virtuality works really uniformly - also for destructors.
This is a decade old topic :)
Read last 5 paragraphs of Item #7 on "Effective C++" book for details, starts from "Occasionally it can be convenient to give a class a pure virtual destructor...."
we need to make destructor virtual bacause of the fact that , if we dont make the destructor virtual then compiler will only destruct the contents of base class , n all the derived classes will remain un changed , bacuse compiler will not call the destructor of any other class except the base class.
Related
Is it good practice to make a base class constructor protected if I want to avoid instances of it? I know that I could as well have a pure virtual dummy method, but that seems odd...
Please consider the following code:
#include <iostream>
using std::cout;
using std::endl;
class A
{
protected:
A(){};
public:
virtual void foo(){cout << "A\n";};
};
class B : public A
{
public:
void foo(){cout << "B\n";}
};
int main()
{
B b;
b.foo();
A *pa = new B;
pa->foo();
// this does (and should) not compile:
//A a;
//a.foo();
return 0;
}
Is there a disadvantage or side-effect, that I don't see?
It is common practice to make base class constructors protected. When you have a pure-virtual function in your base class, this is not required, as you wouldn't be able to instantiate it.
However, defining a non-pure virtual function in a base class is not considered good practice, but heavily depends on your use case and does not harm.
There isn't any disadvantage or side-effect. With a protected constructor you just tell other developers that your class is only intended to be used as a base.
What you want to achieve is normally done via the destructor, instead of the constructors, just beacause you can steer the behavior you need with that one function instead of having to deal with it with every new constructor you write. It's a common coding style/guideline, to
make the destructor public, if you want to allow instances of the class. Often those classes are not meant to be inherited from.
make the destructor pure virtual and public, if you want to use and delete the class in a polymorphic context but don't want to allow instances of the class. In other words, for base classes that are deleted polymorphcally.
make the destructor nonvirtual and protected, if you don't want to allow instances of the class and don't want to delete its derivates polymorphically. Normally, you then don't want to use them polymorphically at all, i.e. they have no virtual functions.
Which of the latter two you chose is a design decision and cannot be answered from your question.
It does what you're asking.
However I'm not sure what you are gaining with it. Someone could just write
struct B : A {
// Just to workaround limitation imposed by A's author
};
Normally it's not that one adds nonsense pure-virtual functions to the base class... it's that there are pure virtual functions for which no meaningful implementation can be provided at the base level and that's why they end up being pure virtual.
Not being able to instantiate that class comes as a nice extra property.
Make the destructor pure virtual. Every class has a destructor, and a base class should usually have a virtual destructor, so you are not adding a useless dummy function.
Take note that a pure virtual destructor must have a function body.
class AbstractBase
{
public:
virtual ~AbstractBase() = 0;
};
inline AbstractBase::~AbstractBase() {}
If you don't wish to put the destructor body in the header file, put it in the source file and remove inline keyword.
I have a class declared as follow:
class TestFoo {
public:
TestFoo();
virtual void virtualFunction();
void nonVirtualFunction();
};
that I try to implement this way
TestFoo::TestFoo(){}
void TestFoo::nonVirtualFunction(){}
which on compilation returns the error:
undefined reference to vtable for TestFoo
I tried :
TestFoo::TestFoo(){}
void TestFoo::nonVirtualFunction(){}
void TestFoo::virtualFunction(){}
which compiles ok which is consistent to the answers to these posts:
Undefined reference to vtable
undefined reference to vtable
What confuses me is that I thought the whole point of declaring a virtual function is that I would not need to define it. In this example, I am not planning to create any instance of TestFoo, but to create instances of (concrete) classes inheriting from TestFoo. But still, I want to define the function nonVirtualFunction for every subclasses of TestFoo.
Something I did not get right ?
Thanks !
the whole point of declaring a virtual function is that I would not
need to define it
Not quite, it says "I may want to replace the implementation of this function by something else in a derived class."
I may have misunderstood your question, but you seem to imply that you don't think you can define pure virtual member function in C++, which you can. You can declare one as follows.
virtual void virtualFunction() = 0;
Normally, a pure virtual function won't be defined, but of course you can. That says "There is no default implementation of this function because it won't always make sense, but I'll provide you with an implementation that you can opt into."
By the way, if a class has any virtual functions, you should also define a virtual destructor, as it is perfectly legal (and often recommended) to have a base class (smart) pointer to a derived class - without a virtual destructor, the object may not be deleted correctly.
... I thought the whole point of declaring a
virtual function is that I would not need to define it ...
For that facility you have a feature called pure virtual methods:
virtual void virtualFunction() = 0; // no linking error now
Note that, a virtual method cannot remain unimplemented. The reason is that for every virtual method declared inside a class body there has to be a vtable entry. Failing to find its body results in linking error.
Purpose of this restriction:
Unless a class is abstract - that is it has at least one virtual function - there is no way you can guarantee to the compiler that you are not going to declare an object of TestFoo. What happens when you do following:
DerivedOfTestFoo obj1;
TestFoo obj2 = obj1, *p = &obj2; // object slicing
p->virtualFunction(); // where is the body?
Other situation; in constructor there is no virtual mechanism:
TestFoo::TestFoo () {
this->virtualFunction(); // where is the body?
}
We can conclude that, compilers follow the rule, "Better to be safe than sorry". :)
Your description matches perfectly with the case of an abstract class. Declare your virtual function as:
virtual void VirtualFunction () = 0;
This means that you are not implementing the function in this class. As a result, the class becomes abstract. That is, no bare objects of this class can be instantiated.
Also, you should provide a virtual destructor.
Update: Some clarifications...
The language allows you to redefine a non-virtual function. Though, the wrong version might be called in some cases:
derived D; // rB is a reference to base class but it
base & rB=D; // points to an object of the derived class
rB.NonVirtualFunction (); // The base-class version is called
For this reason, redefining a non-virtual function is strongly discouraged nowadays. See Scott Meyers' "Effective C++, Third Edition: 55 Specific Ways to Improve Your Programs and Designs", item 36: "Never redefine an inherited non-virtual function."
See also item 7: "Declare destructors virtual in polymorphic base classes". An example:
base * pB = new derived;
delete pB; // If base's destructor is not virtual,
// ~derived() will not be called.
In case you wonder why isn't everything virtual by default, the reason is that calling a virtual function is slightly slower than calling a non-virtual one. Oh, and objects of classes with virtual functions occupy a few more bytes each.
If you want make this virtual function as pure virtual function,do not want to define it then, virtual void virtualFunction() = 0;
When I write interface classes in C++, I choose either of the following 2 options
class Interface
{
public:
virtual R1 f1(p11, p12 , ...) = 0;
...
virtual Rn fn(pn1, pn2 , ...) = 0;
virtual ~Interface() {}
}
or
class Interface
{
public:
virtual R1 f1(p11, p12 , ...) = 0;
...
virtual Rn fn(pn1, pn2 , ...) = 0;
virtual ~Interface() = 0;
}
Interface::~Interface() {}
The first version is shorter to write
The second is attractive in that all functions of the interface are pure virtual
Is there any reason I should prefer one or the other method (or perhaps a third one)?
Thanks
As I understand, the purpose of making virtual function pure virtual is to force the derived classes to either provide implementation for it or choose the default implementation by explicitly writing Base::f() in the Derived::f().
So if that is true, then what is the purpose of making virtual destructor pure virtual? Does it force the derived classes to provide implementation for Base::~Base()? Can the derived classes implement Base::~Base()? No.
So that means, the first version with virtual destructor seems enough for almost all purposes. After all, the most common purpose of virtual destructor is that the clients can correctly delete objects of the derived classes through pointers of type Base*.
However, if you make all functions in Base virtual only, not pure virtual, and provide implementations for them (actually you've to provide), and at the same time you want to make Base abstract type, then having a pure virtual destructor in Base is the only solution:
class Base
{
public:
virtual void f() {}; //not pure virtual
virtual ~Base() = 0; //pure - makes Base abstract type!
};
Base::~Base() {} //yes, you have to do this as well.
Base *pBase = new Base(); // error - cannot create instance!
Hope that helps.
To me, the dtor is not part of the interface. The fi() would have analogues in other languages, not the dtor. Likewise, you could write pre- and post- conditions for the fi(), but not the dtor. This makes it just a C++ wart, and the first technique is the most comfortable way of dealing with it.
Okay, found a link and so thought I would mention it as an answer:
Are inline virtual functions really a non-sense?
I've seen compilers that don't emit
any v-table if no non-inline function
at all exists (and defined in one
implementation file instead of a
header then). They would throw errors
like missing vtable-for-class-A or
something similar, and you would be
confused as hell, as i was.
Indeed, that's not conformant with the
Standard, but it happens so consider
putting at least one virtual function
not in the header (if only the virtual
destructor), so that the compiler
could emit a vtable for the class at
that place. I know it happens with
some versions of gcc.
(Johannes Schaub)
Its slightly different from your second case (suggests actually taking the function out of the header file altogether so as not to fall victim to gcc problem) but I thought I would mention it. Quirks of gcc can occasionally bite.
In the first case, the derived class may choose whether or not to implement a destructor.
In the second case, the pure virtual destructor must be overridden, so the derived class is forced to implement a destructor.
Unless you have some reason why you want to force this, I would go with the first case.
Just what the topic asks. Also want to know why non of the usual examples of CRTP do not mention a virtual dtor.
EDIT:
Guys, Please post about the CRTP prob as well, thanks.
Only virtual functions require dynamic dispatch (and hence vtable lookups) and not even in all cases. If the compiler is able to determine at compile time what is the final overrider for a method call, it can elide performing the dispatch at runtime. User code can also disable the dynamic dispatch if it so desires:
struct base {
virtual void foo() const { std::cout << "base" << std::endl; }
void bar() const { std::cout << "bar" << std::endl; }
};
struct derived : base {
virtual void foo() const { std::cout << "derived" << std::endl; }
};
void test( base const & b ) {
b.foo(); // requires runtime dispatch, the type of the referred
// object is unknown at compile time.
b.base::foo();// runtime dispatch manually disabled: output will be "base"
b.bar(); // non-virtual, no runtime dispatch
}
int main() {
derived d;
d.foo(); // the type of the object is known, the compiler can substitute
// the call with d.derived::foo()
test( d );
}
On whether you should provide virtual destructors in all cases of inheritance, the answer is no, not necessarily. The virtual destructor is required only if code deletes objects of the derived type held through pointers to the base type. The common rule is that you should
provide a public virtual destructor or a protected non-virtual destructor
The second part of the rule ensures that user code cannot delete your object through a pointer to the base, and this implies that the destructor need not be virtual. The advantage is that if your class does not contain any virtual method, this will not change any of the properties of your class --the memory layout of the class changes when the first virtual method is added-- and you will save the vtable pointer in each instance. From the two reasons, the first being the important one.
struct base1 {};
struct base2 {
virtual ~base2() {}
};
struct base3 {
protected:
~base3() {}
};
typedef base1 base;
struct derived : base { int x; };
struct other { int y; };
int main() {
std::auto_ptr<derived> d( new derived() ); // ok: deleting at the right level
std::auto_ptr<base> b( new derived() ); // error: deleting through a base
// pointer with non-virtual destructor
}
The problem in the last line of main can be resolved in two different ways. If the typedef is changed to base1 then the destructor will correctly be dispatched to the derived object and the code will not cause undefined behavior. The cost is that derived now requires a virtual table and each instance requires a pointer. More importantly, derived is no longer layout compatible with other. The other solution is changing the typedef to base3, in which case the problem is solved by having the compiler yell at that line. The shortcoming is that you cannot delete through pointers to base, the advantage is that the compiler can statically ensure that there will be no undefined behavior.
In the particular case of the CRTP pattern (excuse the redundant pattern), most authors do not even care to make the destructor protected, as the intention is not to hold objects of the derived type by references to the base (templated) type. To be in the safe side, they should mark the destructor as protected, but that is rarely an issue.
Very unlikely indeed. There's nothing in the standard to stop compilers doing whole classes of stupidly inefficient things, but a non-virtual call is still a non-virtual call, regardless of whether the class has virtual functions too. It has to call the version of the function corresponding to the static type, not the dynamic type:
struct Foo {
void foo() { std::cout << "Foo\n"; }
virtual void virtfoo() { std::cout << "Foo\n"; }
};
struct Bar : public Foo {
void foo() { std::cout << "Bar\n"; }
void virtfoo() { std::cout << "Bar\n"; }
};
int main() {
Bar b;
Foo *pf = &b; // static type of *pf is Foo, dynamic type is Bar
pf->foo(); // MUST print "Foo"
pf->virtfoo(); // MUST print "Bar"
}
So there's absolutely no need for the implementation to put non-virtual functions in the vtable, and indeed in the vtable for Bar you'd need two different slots in this example for Foo::foo() and Bar::foo(). That means it would be a special-case use of the vtable even if the implementation wanted to do it. In practice it doesn't want to do it, it wouldn't make sense to do it, don't worry about it.
CRTP base classes really ought to have destructors that are non-virtual and protected.
A virtual destructor is required if the user of the class might take a pointer to the object, cast it to the base class pointer type, then delete it. A virtual destructor means this will work. A protected destructor in the base class stops them trying it (the delete won't compile since there's no accessible destructor). So either one of virtual or protected solves the problem of the user accidentally provoking undefined behavior.
See guideline #4 here, and note that "recently" in this article means nearly 10 years ago:
http://www.gotw.ca/publications/mill18.htm
No user will create a Base<Derived> object of their own, that isn't a Derived object, since that's not what the CRTP base class is for. They just don't need to be able to access the destructor - so you can leave it out of the public interface, or to save a line of code you can leave it public and rely on the user not doing something silly.
The reason it's undesirable for it to be virtual, given that it doesn't need to be, is just that there's no point giving a class virtual functions if it doesn't need them. Some day it might cost something, in terms of object size, code complexity or even (unlikely) speed, so it's a premature pessimization to make things virtual always. The preferred approach among the kind of C++ programmer who uses CRTP, is to be absolutely clear what classes are for, whether they are designed to be base classes at all, and if so whether they are designed to be used as polymorphic bases. CRTP base classes aren't.
The reason that the user has no business casting to the CRTP base class, even if it's public, is that it doesn't really provide a "better" interface. The CRTP base class depends on the derived class, so it's not as if you're switching to a more general interface if you cast Derived* to Base<Derived>*. No other class will ever have Base<Derived> as a base class, unless it also has Derived as a base class. It's just not useful as a polymorphic base, so don't make it one.
The answer to your first question: No. Only calls to virtual functions will cause an indirection via the virtual table at runtime.
The answer to your second question: The Curiously recurring template pattern is commonly implemented using private inheritance. You don't model an 'IS-A' relationship and hence you don't pass around pointers to the base class.
For instance, in
template <class Derived> class Base
{
};
class Derived : Base<Derived>
{
};
You don't have code which takes a Base<Derived>* and then goes on to call delete on it. So you never attempt to delete an object of a derived class through a pointer to the base class. Hence, the destructor doesn't need to be virtual.
Firstly, I think the answer to the OP's question has been answered quite well - that's a solid NO.
But, is it just me going insane or is something going seriously wrong in the community? I felt a bit scared to see so many people suggesting that it's useless/rare to hold a pointer/reference to Base. Some of the popular answers above suggest that we don't model IS-A relationship with CRTP, and I completely disagree with those opinions.
It's widely known that there's no such thing as interface in C++. So to write testable/mockable code, a lot of people use ABC as an "interface". For example, you have a function void MyFunc(Base* ptr) and you can use it this way: MyFunc(ptr_derived). This is the conventional way to model IS-A relationship which requires vtable lookups when you call any virtual functions in MyFunc. So this is pattern one to model IS-A relationship.
In some domain where performance is critical, there exists another way(pattern two) to model IS-A relationship in a testable/mockable manner - via CRTP. And really, performance boost can be impressive(600% in the article) in some cases, see this link. So MyFunc will look like this template<typename Derived> void MyFunc(Base<Derived> *ptr). When you use MyFunc, you do MyFunc(ptr_derived); The compiler is going to generate a copy of code for MyFunc() that matches best with the parameter type ptr_derived - MyFunc(Base<Derived> *ptr). Inside MyFunc, we may well assume some function defined by the interface is called, and pointers are statically cast-ed at compile time(check out the impl() function in the link), there's no overheads for vtable lookups.
Now, can someone please tell me either I am talking insane nonsense or the answers above simply did not consider the second pattern to model IS-A relationship with CRTP?
Starting to use PC-Lint on an existing code base (fear and trepidation).
One thing that it complains about is the following:
class IBatch
{
public:
virtual void StartBatch() =0;
virtual int CommitBatch() =0;
};
Which when another class derives from this to use it like an interface
base class 'IBatch' has no destructor
So, the question: when you create Interface classes like the above, do you always include a virtual destructor? Why? (is it a style or a coding error?)
EDIT: Should have said that I do not expect or want the user of IBatch to destruct, they are a consumer of a service only, through this interface to some external implementing class (if that would make a difference)
A base class destructor should be either public and virtual, or protected and nonvirtual.
(Herb Sutter, Guru of the Week #18: "Virtuality")
Coding error - The destructor for your derived class will never get called if called via pointer to base class.
When you implement IBatch and you refer to your derived class by a pointer to a base class (pointer to IBatch) and you call delete on that pointer to base class you might end up with memory leak because the destructor for your derived class will never get called.
The basic rule is when a class has at least one virtual method it needs to have virtual destructor.
class IBatch
{
public:
virtual void f() = 0;
};
class A : public IBatch
{
public:
void f() {}
~A() {}
};
IBatch * a = new A();
a->f(); // calls A::f()
delete a; // calls IBatch::~IBatch() not A::~A()
If there are virtual functions, there needs to be a virtual destructor. Always. It does not matter that it's only an interface class -- it still needs the virtual destructor.
Either that, or it needs a protected nonvirtual destructor. But then you cannot delete the object using the interface pointer.
A class with virtual functions but no virtual destructor is suspect, and most likely wrong: see a good and more precise explanation here.
So, the question: when you create
Interface classes like the above, do
you always include a virtual
destructor? Why? (is it a style or a
coding error?)
Well it depends really. If you ever call delete on an IBatch pointer it probably won't do what you are expecting. Of course if you have something like virtual Init/Shutdowns or AddRef/Releases then its not really a problem.
Compiler puts default destructor that is not virtual, which implies that a 'delete' on a pointer to the virtual base class will succeed with a resulting memory leak. Therefore, it is an implementation flaw, neither style or coding error.