C++11 interface pure virtual destructor - c++

UPD. There is a mark that it is a duplicate of this question. But in that question OP asks HOW to use default to define pure virtual destructor. This question is about what the difference.
In C++ (latest standard if possible) what the real difference between defining pure virtual destructor with empty body implementation and just a empty body (or default)?
Variant 1:
class I1 {
public:
virtual ~I1() {}
};
Variant 2.1:
class I21 {
public:
virtual ~I21() = 0;
};
I21::~I21() {}
Variant 2.2:
class I22 {
public:
virtual ~I22() = 0;
};
I22::~I22() = default;
Update I found at least 1 difference between Variant 1 and Variants 2.1/2.2:
std::is_abstract::value is false for Variant 1, and true for Variants 2.1 and 2.2.
Demo
May be someone can found difference between 2.1 and 2.2?

The difference between I1 and I2*, as you pointed out, is that adding = 0 makes the class abstract. In fact, making the destructor pure virtual is a trick to make a class abstract when you don't have any other function to be pure virtual. And I said it's a trick because the destructor cannot be left undefined if you ever want to destruct any derived class of it (and here you will), then you still need to define the destructor, either empty or defaulted.
Now the difference between empty or defaulted destructor/constructor (I21 and I22) is way more obscure, there isn't much written out there. The recommended one is to use default, both as a new idiom to make your intentions clearer, and apparently, to give the compiler a chance for optimization. Quoting msdn
Because of the performance benefits of trivial special member functions, we recommend that you prefer automatically generated special member functions over empty function bodies when you want the default behavior.
There are no visible differences between the two, apart from this possible performance improvement. = default is the way to go from C++11 on.

All I could find was:
§12.4 (5.9)
A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any
derived class are created in the program, the destructor shall be defined. If a class has a base class with a
virtual destructor, its destructor (whether user- or implicitly-declared) is virtual.
leading to:
§10.4 (the class is now abstract)
10.4 (2) says:
A pure virtual function need be defined only if called with, or as if with (12.4), the qualified-id syntax (5.1).
But the narrative on destructors in §12.4 talks about destructors always being called as if by their fully qualified name (in order to prevent ambiguity).
Which means that:
the destructor must be defined, even if pure virtual, and
the class is now abstract.

Variant 1 will allow you to have an instance of the class. Variant 2.1, 2.2 won't allow instances, but allows instances of descendants. This, for example works (and is able to confuse many people), while removing the marked line will make compile fail:
class I21 {
public:
virtual ~I21() = 0;
};
I21::~I21() {} // remove this and it'll not compile
class I22 : public I21
{
public:
virtual ~I22() {}
};
int main() {
I22 i;
return 0;
}
The reason behind, the destructor chain calls I21::~I21() directly and not via interface. That said, it's not clear what your goal is with pure virtual destructors. If you'd like to avoid instantiation (i.e., static class), you might consider deleting the constructor instead; if you'd like descendants that can be instantiated but not this class, perhaps you need a pure virtual member function that's implemented in descendants.

Related

default override of virtual destructor

Everyone knows that the desructor of base class usually has to be virtual. But what is about the destructor of derived class? In C++11 we have keyword "override" and ability to use the default destructor explicitly.
struct Parent
{
std::string a;
virtual ~Parent()
{
}
};
struct Child: public Parent
{
std::string b;
~Child() override = default;
};
Is it correct to use both keywords "override" and "=default" in the destructor of Child class? Will compiler generate correct virtual destructor in this case?
If yes, then can we think that it is good coding style, and we should always declare destructors of derived classes this way to ensure that base class destructors are virtual?
Is it correct to use both keywords "override" and "=default" in the destructor of Child class? Will compiler generate correct virtual destructor in this case?
Yes, it is correct. On any sane compiler, if the code compiles without error, this destructor definition will be a no-op: its absence must not change the behavior of the code.
can we think that it is good coding style
It's a matter of preference. To me, it only makes sense if the base class type is templated: it will enforce a requirement on the base class to have a virtual destructor, then. Otherwise, when the base type is fixed, I'd consider such code to be noise. It's not as if the base class will magically change. But if you have deadheaded teammates that like to change things without checking the code that depends on what they may be possibly breaking, it's best to leave the destructor definition in - as an extra layer of protection.
override is nothing more than a safety net. Destructor of the child class will always be virtual if base class destructor is virtual, no matter how it is declared - or not declared at all (i.e. using implicitly declared one).
According to the CppCoreGuidelines C.128 the destructor of the derived class should not be declared virtual or override.
If a base class destructor is declared virtual, one should avoid declaring derived class destructors virtual or override. Some code base and tools might insist on override for destructors, but that is not the recommendation of these guidelines.
UPDATE: To answer the question why we have a special case for destructors.
Method overriding is a language feature that allows a subclass or child class to provide a specific
implementation of a method that is already provided by one of its superclasses or parent classes. The implementation in the subclass overrides (replaces) the implementation in the superclass by providing a method that has same name, same parameters or signature, and same return type as the method in the parent class.
In other words, when you call an overridden method only the last implementation of that method (in the class hierarchy) is actually executed while all the destructors (from the last child to the root parent) must be called to properly release all the resources owned by the object.
Thus we don't really replace (override) the destructor, we add additional one into the chain of object destructors.
UPDATE: This CppCoreGuidelines C.128 rule was changed (by 1448, 1446 issues) in an effort to simplify already exhaustive list of exceptions. So the general rule can be summarized as:
For class users, all virtual functions including destructors are equally polymorphic.
Marking destructors override on state-owning subclasses is textbook hygiene that you should all be doing by routine (ref.).
There is (at least) one reason for using override here -- you ensure that the base class's destructor is always virtual. It will be a compilation error if the derived class's destructor believes it is overriding something, but there is nothing to override. It also gives you a convenient place to leave generated documentation, if you're doing that.
On the other hand, I can think of two reasons not to do this:
It's a little weird and backwards for the derived class to enforce behavior from the base class.
If you define a destuctor in the header (or if you make it inline), you do introduce the possibility for odd compilation errors. Let's say your class looks like this:
struct derived {
struct impl;
std::unique_ptr<derived::impl> m_impl;
~derived() override = default;
};
You will likely get a compiler error because the destructor (which is inline with the class here) will be looking for the destructor for the incomplete class, derived::impl.
This is my round-about way of saying that every line of code can become a liability, and perhaps it's best to just skip something if it functionally does nothing. If you really really need to enforce a virtual destructor in the base class from the parent class, someone suggested using static_assert in concert with std::has_virtual_destructor, which will produce more consistent results, IMHO.
I think "override" is kind of misleading on destructor.
When you override virtual function, you replace it.
The destructors are chained, so you can't override destructor literally
The CPP Reference says that override makes sure that the function is virtual and that it indeed overrides a virtual function. So the override keyword would make sure that the destructor is virtual.
If you specify override but not = default, then you will get a linker error.
You do not need to do anything. Leaving the Child dtor undefined works just fine:
#include <iostream>
struct Notify {
~Notify() { std::cout << "dtor" << std::endl; }
};
struct Parent {
std::string a;
virtual ~Parent() {}
};
struct Child : public Parent {
std::string b;
Notify n;
};
int main(int argc, char **argv) {
Parent *p = new Child();
delete p;
}
That will output dtor. If you remove the virtual at Parent::~Parent, though, it will not output anything because that is undefined behavior, as pointed out in the comments.
Good style would be to not mention Child::~Child at all. If you cannot trust that the base class declared it virtual, then your suggestion with override and = default will work; I would hope that there are better ways to ensure that instead of littering your code with those destructor declarations.
Though destructors are not inherited there is clear written in the Standard that virtual destructors of derived classes override destructors of base classes.
From the C++ Standard (10.3 Virtual functions)
6 Even though destructors are not inherited, a destructor in a derived
class overrides a base class destructor declared virtual; see 12.4 and
12.5.
On the other hand there is also written (9.2 Class member)
8 A virt-specifier-seq shall contain at most one of each virt-specifier.
A virt-specifier-seq shall appear only in the declaration of a
virtual member function (10.3).
Though destructors are called like special member functions nevertheless they are also member functions.
I am sure the C++ Standard should be edited such a way that it was unambiguous whether a destructor may have virt-specifier override. At present it is not clear.

Destructors in non-polymorphic base classes

Consider this code:
class A {
public:
void fun() {}
};
class B : public A {
public:
void fun() {}
};
int main()
{
A *p = new B;
delete p;
}
Classes A and B are not polymorphic, and neither class declares a destructor. If I compile this code with g++ -Wall, the GCC compiler happily compiles the code.
But if I add virtual to void fun() in A, the compiler issues this warning: "deleting object of polymorphic class type ‘A’ which has non-virtual destructor might cause undefined behavior".
I'm quite aware of the dangers of using non-virtual destructors. But the code above makes me wonder about two things:
Why do I need to write an empty virtual destructor in the base class when I'm not using destructors at all?
Why is the empty virtual destructor not required if the base class contains no other virtual functions?
EDIT
It appears that I need to clarify the thing that bothers me:
The above code declares no destructors.
If I declare a virtual function, the compiler complains about the missing virtual destructor. My conclusion: If the class is polymorphic, I need to write a virtual destructor if delete p is to work correctly.
But if I declare no virtual function (as in the initial example above), the compiler does not complain about a missing virtual destructor. My conclusion: If the class is not polymorphic, I do not need to write a virtual desctructor, and delete p will work correctly anyway.
But that last conclusion sounds intuitively wrong to me. Is it wrong? Should the compiler have complained in both cases?
Following up on PaulMcKenzie's and KerrekSB's comments, here is the answer to the two questions in the original post:
The class always has a destructor, even when the programmer doesn't explicitly write one. It is necessary to declare an empty virtual destructor in order to prevent the system from automatically generating a non-virtual one.
In the sample code provided, you do need a virtual destructor, even when there is no other virtual function in the class. The fact that GCC doesn't complain in this case is probably a bug in the compiler (or at least a shortcoming).
The background for this is found in §5.3.5 of the C++11 standard, which says, "if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined." (Italics mine.)
You are making an upcasting, in other words: a polymorphic use of the class B. If the class A has not virtual members, the compiler does not generate VTABLE for class A and it is not require a virtual destructor (note that your upcasting has no sense without polymorphism use). While if the class A declares virtual members, a VTABLE is generated by compiler, in this case you should provide a virtual destructor.
If your want polymorphic behaviour you need to define at least one virtual function in order compiler should generate v-table for your class.
Because C++ class contains two special functions (constructor and destructor) which used for every object it a good choice to make destructor virtual.
When you write delete p you really call a destructor for object associated with pointer p. If you not declare a destructor as virtual you've get error prone code.
Before your declare at least one of member function as virtual compiler did not expect that you intend using your class as polymorphic. In C++ phylosophy: "You should not pay for functionallity that you will never use". E.g. in simple case destructor should not be virtual.

Why does it make sense to give definition for a pure virtual function?

Scott said on Effective C++, 3rd Edition, pg. 43 that to make an abstract class, we just need to give it a pure virtual destructor:
class AWOV { // AWOV = "Abstract w/o Virtuals"
public:
virtual ~AWOV() = 0; // declare pure virtual destructor
};
Then, he went on said that there is one twist: we must provide a definition for the pure virtual destructor:
AWOV::~AWOW() {} // definition of pure virtual dtor
My question is, by specifiying = 0, for pure virtual functions, we are saying that the function cannot have any definition for the class where this pure virtual function is declared.
Why is it OK to provide a definition (even it is empty) for the pure virtual destructor here?
"we are saying that the function cannot have any definition for the class where this pure virtual function is declared."
That's not what pure virtual means. Pure virtual only means that the containing class cannot be instantiated (is abstract), so it has to be subclassed, and subclasses must override the method. E.g.,
struct A {
virtual ~A() = 0;
};
A::~A() {}
struct B : A {};
int main()
{
A a; // error
B b; // ok
}
Here, the B destructor is implicitly defined. If it was another method that is pure virtual, you'd have to explicitly override it:
struct A {
virtual void foo() = 0;
};
void A::foo() {}
struct B : A {};
int main()
{
B b; // error
}
Providing a definition for a pure virtual method is desirable when the base class must be abstract but still provide some default behavior.
In the specific case of a destructor, it has to be provided because it will be called automatically when subclass instances are destroyed. A program that tries to instantiate a subclass of a class with a pure virtual destructor without a definition will not pass the linker.
Making it pure forces derived (non-abstract) classes to implement their own.
Providing an implementation allows derived classes to invoke base class behavior (which destructors do by default).
There are 2 cases.
Pure virtual destructor
This case is specifically treated by the standard.
12.4 Destructors [class.dtor]
9) A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any
derived class are created in the program, the destructor shall be defined. If a class has a base class with a
virtual destructor, its destructor (whether user- or implicitly-declared) is virtual.
The case of the destructor is different because all destructors are called in an inheritance hierearchy (assuming correct deletion) in reverse order of construction, even if not explicitly. So the base class destructor is called when the object gets deleted - that's why it needs an implementation.
Pure virtual method
These differ from destructors in that they're not required to be implemented, nor do they need an implementation. The difference for the missing requirement is that when a Derived::foo() gets called, it doesn't automatically call Base::foo() (not that it could, since it can or can not be implemented).
Why you would want to implement a pure virtual method depends on the case. I look at the pure specifier as a hint to the programmer, as opposed to related to the logic. It tells you - the programmer - that you should implement that method. It doesn't really matter if the base class has an implementation or not.
by specifiying = 0, for pure virtual functions, we are saying that the function cannot have any definition for the class where this pure virtual function is declared.
Not really. You're saying derived non-abstract classes have to override that function. This doesn't prevent you from implementing it yourself.
This is not necessary for all pure virtual functions. Not at all.
This way, the derived classes will still be forced to override the implementation, but there will be a default implementation in the base class, in case you need to call it. And that's the case here - because you're dealing with a destructor: when a derived object is being destroyed, its destructor is called and its base classes destructors are called as well. That's why you need an implementation for A::~A.
By making a function pure virtual we force the user of the class to replace the function with another in the derived class.
The base class function can still be called with BaseClass::myfunction(...)
Now the base class might want to provide some core functionality that the derived class may use if it chooses to do so.
Correct answer:
Suppose there are 2 pure virtual functions in class. Now assume that both have implementation. The reason for providing implementation for PVF is that the Base class method can act as default behavior if Base class is derived by child by implementing these PVF methods(to make class as concrete)

what to do with the destructors in an interface

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.

Why do we need a pure virtual destructor in C++?

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.