I know you shouldn't call any virtual function in the ctor or dtor of the base class, but what about from that of the most derived class? Should be fine right? E.g.
class base {
...
virtual void free() = 0;
};
class child : public base {
...
free() {/* free memory */}
~child() {free();}
};
Well, you can do it, but the dynamic type of *this inside child::~child() is child, and not anything more derived. So when you have a further derived class class foo : child which overrides free(), then the overridden function will not be called.
There's nothing wrong with calling a virtual function from a constructor or destructor, base class or otherwise. But you have to know what it does: the dynamic type is the class being constructed or destroyed, so it won't call an override in a class derived from the one that's being constructed or destroyed. In particular, if the function is pure virtual, you won't get an override, and the behavior is undefined. So a good rule is "don't call pure virtual functions from constructors or destructors. In your example, class::free is not pure virtual, so there's no problem calling it.
Related
I wrote a base and derived class that had no virtual functions. The use of virtual is typically the guide I see for when to use a virtual destructor.
However, while my classes have no virtual functions I am using the classes in a polymorphic way when I pass them around. Therefore, class Base should implement a virtual destructor?
class Base;
class Derived;
main()
{
base& baseVar = derived();
foo(baseVar);
}
There is no polymorphism because you call (will call) non-virtual functions using the referemce. That is in your example you simply call (will call) functions of the base class.
Moreover this statement
base& baseVar = derived();
should not be compiled because you bind a temporary object with a non-const reference.
There must be
const base& baseVar = derived();
As for the destructor in your example then there is no need to have a virtual destructor. Becasue you defined a reference to a temporary object of the derived class. In this case for the temporary object will be called its own destructor. That is at first the destructor of the base class will be called (from the destructor of the derived class) and then the body of the destructor of the derived class will be executed.
The vertual destructor would be need if you would allocate a derived memory in the heap and assign the address of the allocated memory to a pointer of the base class. And when you would call operator delete for this pointer then if you have no virtual destructor then the only destructor of the base class would be called.
For example
class Base;
class Derived;
main()
{
base* baseVar = new derived();
delete baseVar; // base shall have a virtual destructor
}
You should use a virtual destructor if your program will ever find itself in the position where it will be deleting an instance of a derived class through a base class pointer to ensure the correct destructor is called.
See this question for more detail When to use virtual destructors?
I know the cases where pure virtual destructors are needed. I also know that If we don't provide an implementation for them it will give me a linker error. What I don't understand is why this should be the case in a code fragment as shown below:
int main()
{
Base * p = new Derived;
}
Here there is no delete, so no call to destructor and so no need for its implementation(assuming it is supposed to behave like other normal functions which are declared but not defined, linker complains only when we call them)...or am I missing something?
I need to understand why this should be a special case?
Edit: based on comments from BoBTFish
Here are my Base and Derived classes
class Base
{
public:
Base(){}
virtual ~Base() = 0;
};
class Derived : public Base
{
};
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.
C++11 standard:
12.4 Destructors
Paragraph 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.
Destructors differ from other virtual functions in this way, because they are special and automatically invoked in bases, with no possible, useful or meaningful way to prevent it.
[C++11: 12.4/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.
Bases are always destroyed, and to do this, a base destructor definition is required. Conversely, other overridden virtual functions are not invoked automatically at all. Hence the special-case requirement.
struct Base
{
virtual ~Base() = 0; // invoked no matter what
virtual void foo() = 0; // only invoked if `Base::foo()` is called
};
Base::~Base() {}
/* void Base::foo() {} */
struct Derived : Base
{
virtual void foo() { /* Base::foo(); */ }
};
int main()
{
std::unique_ptr<Base> ptr(new Derived());
}
One practical reason is that destructors come first in the list of virtual member functions in the vtable in practically all implementations. And implementations tend to define the vtable itself when it defines the first virtual member function. So, no destructor, no vtable. And the vtable is critical.
From the C++ FAQ:
[11.4] Can I overload the destructor for my class?
No.
I realize this means you cannot change the return type, arguments' types nor the number of arguments. I may be splitting hairs on the syntax of the words, but is it possible to override the Parent's destructor?
class Child : public Parent {
public:
virtual Parent::~Parent() {
// New definition
}
};
And for that matter do it recursively?
class Grandchild : public Child {
public:
Child::Parent::~Parent() {
// An even newer definition
}
};
I've read this and a related post and it makes me think because destructors are not inherited, they cannot be overridden, but I've never seen it explicitly stated.
EDIT: I changed this to reflect the fact that I want to override the Parent's destructor, note Child and Grandchild overriding ~Parent().
The main reason I am doing this is to maintain Parent's interface while changing the way it is destroyed (the entire reason for the child class). I will have something else managing all Parent's created and will explicitly call their destructors at a later time of my choosing.
I may be splitting hairs on the syntax of the words
No, you are definitely not – these are two very different things.
but is it possible to override the destructor?
Yes, and in fact you must do this in many cases. In order for this to work for a polymorphic object, you need to declare the base class destructor as virtual, though:
Parent const& p = Child();
Will properly call p.~Child() at the end of scope because Parent::~Parent is virtual.
Yes, it is possible to override the destructor of a class. In fact, when you define a class hierarchy in which polymorphism is used, you must declare a virtual destructor in the base class.
Overrides of destructors work exactly the same way overrides of normal member functions work in that when you destroy an object by deleteing the object via a pointer to the base class, the destructor of the derived class is properly called. This is why you must have a virtual destructor in the base class for polymorphic hierarchies.
However, there is a difference between virtual destructors and virtual member methods which has nothing to do with the virtual nature of the destructor. That is, when executing code like this:
class A
{
public:
virtual void Foo() {}
virtual ~A() {};
};
class B : public A
{
public:
void Foo() {};
~B() {}
};
int main()
{
A* a = new B;
a->Foo(); // B::Foo() is called
delete a; // B is destroyed via B::~B()
}
...when you call a->Foo(), the method Foo() in B is called. Since B::Foo() doesn't explicitly call A::Foo(), A::Foo() isn't called.
However, when the object is destroyed via delete a;, first the destructor B::~B() is called, and then after that finishes but before control returns to the program, the base class destructor A::~A() is also called.
Of course this is obvious when you think about it, and again this has nothing to do with the virtual nature of the destructor, but it does behave differently than a normal virtual method call, so I thought I'd point it out.
Obligitory Standard Quotation:
[C++03] 12.4/6 : Destructors
After executing the body of the destructor and destroying any
automatic objects allocated within the body, a destructor for class X
calls the destructors for X’s direct members, the destructors for X’s
direct base classes and, if X is the type of the most derived class
(12.6.2), its destructor calls the destructors for X’s virtual base
classes. All destructors are called as if they were referenced with a qualified name, that is, ignoring any possible virtual
overriding destructors in more derived classes. Bases and members are
destroyed in the reverse order of the completion of their
constructor (see 12.6.2). A return statement (6.6.3) in a destructor
might not directly return to the caller; before transferring control
to the caller, the destructors for the members and bases are called.
Destructors for elements of an array are called in reverse order of
their construction (see 12.6).
Yes: you can have virtual destructors, and the only reason is to override them in derived classes.
It looks like this:
class Parent {
public:
virtual ~Parent();
};
class Child : public Parent {
public:
virtual ~Child();
};
class Grandchild : public Child {
public:
~Grandchild(); // virtual is inherited here
};
Note that the destructor isn't overridden by name like ordinary functions, because the name is always that of the class whose instance you're destroying.
Note also that the parent class' destructors are always called too, so you don't need to duplicate their cleanup code: read up on member object and base-class sub-object construction and destruction order for the details.
Terminology
overriding a function means implementing a base-class virtual function in a derived class. You can't change the signature at all (except for using covariant return types). So, an override always has the same signature as an inherited virtual function.
overloading a function means implementing multiple functions with the same name (and in some sense the same scope). So, an overload always has a different signature to the others with the same name, doesn't relate directly to virtual dispatch, and isn't necessarily inherited.
Yes; you can, and should, make a destructor virtual, whenever you have a child class which may be destroyed using a reference to the base class. Static code analysis tools will even complain if you don't offer a virtual destructor.
Consider the following example:
class A
{
public:
A() { a = new int; }
virtual ~A() { delete a; }
private:
int *a;
};
class B final : public A
{
public:
B() { b = new int; }
~B() { delete b; }
private:
int *b;
};
int main()
{
A *a = new B();
delete a;
}
If A's destructor was not virtual, then delete a would only call A's destructor, and you would end up with a memory leak. But because it's virtual, both destructors will be called, in the order ~B() -> ~A().
Given the following example:
class BaseClass
{
BaseClass()
{
};
virtual ~BaseClass()
{
this->Cleanup();
};
virtual void Cleanup()
{
// Do cleanup here.
};
};
class Level1DerivedClass : public BaseClass
{
Level1DerivedClass()
{
};
virtual ~Level1DerivedClass()
{
};
virtual void Cleanup()
{
// Call my base cleanup.
BaseClass::Cleanup();
// Do additional cleanup here.
};
};
class Level2DerivedClass : public Level1DerivedClass
{
Level2DerivedClass()
{
};
~Level2DerivedClass()
{
};
void Cleanup()
{
// Call my base cleanup.
Level1DerivedClass::Cleanup();
// Do additional cleanup here.
};
};
main()
{
Level2DerivedClass * derived2 = new Level2DerivedClass();
delete derived2;
return 0;
}
When I delete my derived class reference, I would EXPECT the flow would be as follows:
Level2DerivedClass destructor is executed.
Because Level1DerivedClass destructor is virtual, it would be executed.
Because BaseClass destructor is virtual, it would be executed.
Because BaseClass::Cleanup and Level1DerivedClass::Cleanup are both virtual, the call from the BaseClass 'this' pointer in the BaseClass destructor would executed the implementation of the most derived class - Level2DerivedClass::Cleanup.
Level2DerivedClass::Cleanup calls its parent's Cleanup implementation.
Level1DerivedClass::Cleanup calls its parent's Cleanup implementation.
What is happening is that it is calling the destructors for each level of inheritance (1 - 3) above the way I'm expecting. But when this->Cleanup() is called from the BaseClass destructor, it only executes its own implementation. I don't understand why this is happening because normally when you instantiate a derived class pointer, cast it as a base class pointer, and call a virtual method from the base class pointer (in this case, 'this'), it still runs the derived class implementation (the whole point of 'virtual', yes?). In my example, Level2DerivedClass::Cleanup and Level1DerivedClass::Cleanup never gets called.
The reason I'm setting it up this way is I want to be able to call my Cleanup code without having to destroy my object, which is why I'm abstracting it from the actual destructor body.
If you have suggestions on a more proper way to do this, I'm all ears. But I would also like an explanation of why my setup doesn't work - what am I misunderstanding?
Thank you in advance for your time.
The rule of thumb is: Never Call Virtual Functions during Construction or Destruction.
They don't behave as you might expect; as each destructor finishes, the dynamic type of this is effectively modified. From [class.cdtor] in the C++ standard:
When a virtual function is called directly or indirectly from a constructor (including the mem-initializer or
brace-or-equal-initializer for a non-static data member) or from a destructor, and the object to which the
call applies is the object under construction or destruction, the function called is the one defined in the
constructor or destructor’s own class or in one of its bases, but not a function overriding it in a class derived
from the constructor or destructor’s class, or overriding it in one of the other base classes of the most derived
object.
The Proper Way Of Doing Things is: clean after yourself, and yourself only, in the destructor. Don't clean after your kids or your parents.
If you want to clean up things not from the destructor, You Are Doing It Wrong. In C++ we have this little thing called RAII, Resource Acquisition Is Initialization. But there's also its dual, which does not seem to have an officially sounding name, but here's something that could work: RDID, Resource Disposal Is Destruction.
Of course you don't have to adhere to the RAII/RDID philosophy, but that would be Not The C++ Way.
This question may sound too silly, however , I don't find concrete answer any where else.
With little knowledge on how late binding works and virtual keyword used in inheritance.
As in the code sample, when in case of inheritance where a base class pointer pointing to a derived class object created on heap and delete operator is used to deallocate the memory , the destructor of the of the derived and base will be called in order only when the base destructor is declared virtual function.
Now my question is :
1) When the destructor of base is not virtual, why the problem of not calling derived dtor occur only when in case of using "delete" operator , why not in the case given below:
derived drvd;
base *bPtr;
bPtr = &drvd; //DTOR called in proper order when goes out of scope.
2) When "delete" operator is used, who is reponsible to call the destructor of the class? The operator delete will have an implementation to call the DTOR ? or complier writes some extra stuff ? If the operator has the implementation then how does it looks like , [I need sample code how this would have been implemented].
3) If virtual keyword is used in this example, how does operator delete now know which DTOR to call?
Fundamentaly i want to know who calls the dtor of the class when delete is used.
<h1> Sample Code </h1>
class base
{
public:
base(){
cout<<"Base CTOR called"<<endl;
}
virtual ~base(){
cout<<"Base DTOR called"<<endl;
}
};
class derived:public base
{
public:
derived(){
cout<<"Derived CTOR called"<<endl;
}
~derived(){
cout<<"Derived DTOR called"<<endl;
}
};
I'm not sure if this is a duplicate, I couldn't find in search.
int main()
{
base *bPtr = new derived();
delete bPtr;// only when you explicitly try to delete an object
return 0;
}
This is due to tha fact that in this case the compiler know everything about the object to be destructed which in this case is drvd and is of type derived. When drvd goes out of scope the compiler inserts code to call its destructer
delete is a keyword for compiler. When compiler see delete it inserts the code to call the destructer and the code to call operator delete to deallocate the memory.Please keep in mind that keyword delete and operater delete are different.
When compiler sees keyword delete being used for a pointer it needs to generate code for its proper destruction. For this it needs to know the type information of the pointer. The only thing the compiler know about the pointer is the pointer type, not the type of object to which the pointer is pointing to. The object to which the pointer is pointing to may be a base class or a derived class. In some cases the type of object may be very clearly defined for example
void fun()
{
Base *base= new Derived();
delete base;
}
But in most cases it is not, for example this one
void deallocate(Base *base)
{
delete base;
}
So the compiler does not know which destructer to call of base or of derived. This is the way then it works
If the Base class does not have a virtual function (member function or destructer). It directly insetrts thr code to call the destructer of base class
If the Base class has virtual functions, then the compiler takes the information of destructer from vtable.
If destructer is not virtual. The vtable will have the address of base destructer and thats what will be called. This is not right since the proper destructer is not being called here. This is why it is always recommended to declare destructer of base class as virtual
If the destructer is virtual the vtable will have correcte address of destructer and compiler will insert proper code over there
+1 Good question BTW.
Look at how the virtual mechanism works for a non destructor method and you'll find a destructor behaves no differently.
There are 2 mechanism in play which may confuse the issue a little
.
Firstly a mechanism that isn't virtual is happening on construction and destruction of an object. The object is constructed from base class to derived class, in that order, and when destructed the destructor order is the reversed, so derived to based class. Nothing new here.
Consider calling a non virtual method on a based class pointer to a derived class object, what happens? The base class implementation is called. Now consider calling a virtual method from a base class pointer to a derived class object, what happens? The derived version of the method is called. Nothing you didn't already know.
Lets now consider the destructor scenario. Call delete on a base class pointer to a derived class object which has a non virtual destructor. The base class destructor is called, and if the base class had been derived from another class, then it's destructor would get called next. Because the virtual mechanism isn't in play , the derived destructor won't be called because destruction starts from the destructor you call in the hierarchy and works it way down to the base class.
Now consider the virtual destructor case. delete is called on a based class pointer to a derived class object. What happens when you call any virtual method on a base class pointer? The derived version gets called. So our derived class destructor is called . What happens during destruction, the object destructs from derived destructor to base class, but this time we started the destruction at the derived class level because of the virtual method mechanism.
Why does a stack object with either a non virtual or virtual destructor destruct from derived to base class when it goes out of scope? Because the destructor of the declared class is called in this case and the virtual mechanism has nothing to do with it.
The compiler generates all necessary code to call destructors in the right order, whether it be a stack object or member variable going out of scope, or a heap object being deleted.
You instantiate the derived type, when it goes out of scope it calls the destructor, virtual or not.
The compiler will generate code which makes a call to the destructors. It does not all happen on compile time. Code generation does, but lookin up what the address of the dtor is happens at runtime. Think about the case where you have more then 1 derived type and you do the delete using a base pointer.
A base class destructor needs to be virtual to make a polymorphic delete call the dtor of the derived type.
If you want to find out more try overloading new and delete.