Why do we need a pure virtual destructor in C++?
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).
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.
};
Pure virtual destructor in C++
Yes. You also need to implement the destructor:
class A {
public:
virtual ~A() = 0;
};
inline A::~A() { }
should suffice.
If you derive anything from A and then try to delete or destroy it, A
's destructor will eventually be called. Since it is pure and doesn't have an implementation, undefined behavior will ensue. On one popular platform, that will invoke the purecall handler and crash.
Edit: fixing the declaration to be more conformant, compiled with http://www.comeaucomputing.com/tryitout/
C++11 interface pure virtual destructor
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.
virtual destructor for pure abstract class
My question is it absolutely must that we define a virtual destructor for "Base" class, even though it does have any data members?
It depends. If you have a case like
base * foo = new child(stuff);
// doing stuff
delete foo;
then you absolutely must have a virtual destructor. Without it you'll never destroy the child
part.
If you have a case like
child * foo = new child(stuff);
// doing stuff
delete foo;
Then you do not need a virtual destructor, as child
's will be called.
So the rule is if you delete polymorphically, you need a polymorphic (virtual) destructor, if not, then you don't
Pure virtual destructor definition inside class gives compilation error
Your second example is correct.
A lot of the other answers assume that it is illegal to have a pure virtual function with a default implementation, however that is incorrect.
In the case of a pure virtual destructor you must have a definition (see the link in xmoex answer).
It is true that:
§10.4/2 a function declaration cannot provide both a pure-specifier
and a definition
However, as you noticed it possible to provide a definition outside of the declaration.
Why a pure virtual destructor needs an implementation
The compiler tries to build the virtual table given a virtual
(pure or not) destructor, and it complains because it can't find the implementation.
virtual
destructors differ from other virtual
functions because they are called when the object is destroyed, regardless of whether it was implemented or not. This requires the compiler to add it to the vf table, even if it's not called explicitly, because the derived class destructor needs it.
Pedantically, the standard requires a pure virtual
destructor to be implemented.
Virtual destructor for pure abstract base classes
Whereas, clang generates warning for:
class A {
public:
virtual ~A() {}
virtual void foo() = 0;
};
using = default
doesn't trigger it.
class A {
public:
virtual ~A() = default;
virtual void foo() = 0;
};
Even if both are valid.
Demo
why we are not obliged to implement pure virtual destructor?
why we are not obliged to implement the pure virtual base's destructor in our derived class?
Because destructors are not overridden.
To help remember that, think about the names: ~Base
and ~Derived
are not the same. Constructors and destructors, instead of working through overriding, are instead called in a chain: the bottom-most destructor runs and then it calls its parent destructor which then runs and then calls its parent destructor etc.
And that is why you must provide the body for a destructor if you want to delete an instance of one of the derived classes, even if it's marked as pure virtual: it needs a body to invoke when reaching it in the destructor chain.
So, what's the deal with virtual destructors to start with? It's done so that the compiler would know to invoke the bottom-most destructor when it encounters a destruction of some class. So destruction does use the virtual table, it's just that it's running the parent class destructor after the derived destructor is done, so it's not standard overriding.
does it mean as long as C++ adds to us four member functions by default: constructor, copy constructor, assignment and Destructor we don't need to implement it in our derived class?
Didn't quite understand the question, but in any case default-added methods are not created pure virtual and can be created in every class in an inheritance chain.
Abstract class object and pure virtual destructor
We cannot make the object of the abstract class
This means that an abstract class cannot be instantiated by itself. It does not mean that objects of abstract class cannot be instantiated as part of a derived object, though: an instance of any derived class is also an instance of its abstract base.
This is where the destructor comes in: if you need one to free private resources allocated in the constructor of the abstract class, the only place to put the clean-up is its destructor.
Is it necessary to make the destruct pure virtual for an abstract class?
It is not necessary to mark the destructor pure virtual. You do it only if you define no other functions that could be marked pure virtual. In any event, you must provide an implementation for the destructor, even if you mark it pure virtual.
C++ Error when using virtual destructor
The problem is
virtual ~ISolution() = 0;
the destructor is not implemented.
Try
virtual ~ISolution() { }
instead.
This is needed even when only instances of the derived class are created, because destructors are special.
In a normal function, the base class implementation needs to be called explicitly, like
void Derived::Foo() {
Base::Foo();
....
}
but for a destructor, this is always done automatically.
Related Topics
Does Copy List Initialization Invoke Copy Ctor Conceptually
Efficiently Convert Between Hex, Binary, and Decimal in C/C++
Glut Deprecation in MAC Osx 10.9, Ide: Qt Creator
How to Read Frames from Videocapture from Secondary Webcam with Opencv
Initializing a Ublas Vector from a C Array
C++ System() Function - How to Collect the Output of the Issued Command
Removing '#Include <Algorithm>' Doesn't Break the Code
How to Speed Up This Histogram of Lut Lookups
Ramifications of C++20 Requiring Two's Complement
Remote Debugging C++ Applications with Eclipse Cdt/Rse/Rdt
How to Convert from Lpctstr to Std::String
Static Variable in the Class Declaration or Definition