This has been provided in my official notes but I spotted an error. Before I take it up to my instructor, I just thought of confirming it here with all my blood brothers- you guys.
#include <iostream.h>
class Base {
public:
virtual void display() { cout << "Base class" << endl; }
};
class Derived: public Base {
// Nothing here
};
void main()
{
Base * ptr;
// Calls Base::display ( )
ptr = new Base ;
ptr ->display();
delete ptr ;
// Calls Base::display ( ) again
ptr = new Derived ;
ptr ->display();
delete ptr ;
}
The output is:
Base class
Base class
I think the problem is in the very last line of the main function. I mean, since the destructor is not virtual, I don't think you can delete a dynamically allocated instance of the derived class type using the pointer of the base class type. What do you think?
I mean, since the destructor is not virtual, I don't think you can delete a dynamically allocated instance of the derived class type using the pointer of the base class type. What do you think?
You can see here and here that this is undefined behavior.
If the base class has no virtual destructor the behavior of such code is simply undefined.
From the C++ standard:
5.3.5 Delete
3 In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined.
When a function is defined as virtual then the compiler will call the function using a pointer to the base using dynamic binding, i.e. the call to the actual function will go through the class vTable to find the relevant implementation of the function. If a function is not defined as virtual then the code generated by the compiler will use static binding, i.e. the compiler will simply call the function it knows. In other words, if you call a non-virtual function on the base class pointer which points to a derived class then the compiler will generate code for calling the base class implementation.
Now, destructor behavior is just a private case of the general behavior described above. As in the absence of a destructor implementation the compiler will generate a default non-virtual destructor for you, the destruction of an object using a base class pointer will just call the base class destructor. You can reproduce this behavior it easily by explicitly defining the non-virtual destructors for both base and derived classes and use the debugger to see that the base class version is the one being called.
Related
In the code below, b is a base-class pointer. However, when I invoke the destructor (either explicitly or implicitly via delete), the derived class destructor is invoked first. I don't understand how this works. There could be any number of derived classes, each with their own destructors. How can the compiler know which derived class destructor to invoke from the base destructor?
#include <iostream>
using namespace std;
class Base {
public:
virtual ~Base() { cout << "Base destructor" << endl; }
};
class Derived : public Base {
public:
~Derived() { cout << "Derived destructor" << endl; }
};
int main(int argc, char * argv[]) {
Base * b = new Derived();
b->~Base(); // delete b; has the same result
}
dynamic binding, the compiler doesn't decide, the runtime does because the destructor is virtual. C++ destruction calls the destructor on the current class and implicitly calls the parent class until it hits the base class.
The call to virtual destructor works the same as a call to any other virtual function, as a result of virtual dispatch via virtual table. Apart from this,
b->~Base(); // delete b; "has the same result"
this is not true, because delete also frees the memory, which you haven't done here. delete b calls a destructor for *b and deallocates raw memory to operating system. You have only destroyed the building but haven't given ground back.
This is done the same way as virtual functions. Its called dynamic binding. When non virtual member functions are resolved statically means at compile-time, virtual members are resolved dynamically means during run time. Compiler maintains a vtable for this. If the object has one or more virtual functions, the compiler puts a hidden pointer in the object called a "virtual-pointer" or "v-pointer." This v-pointer points to a global table called the "virtual-table" or "v-table.". Read more in details from here.
It doesn't. It happens the other way around. Normal virtual function despatching calls the derived destructor, and the derived destructor calls the base destructor.
Note: My first answer was so off-base that I deleted it. It was so far off-base that someone should have down voted my response. This is another try.
In the opening post, master_latch asked:
How can the compiler know which derived class destructor to invoke from the base destructor?
How this happens is implementation specific.
Why this has to happen is "because the standard says so." Here's what the standard says:
C++11 12.4 paragraph 5:
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 non-variant members, the destructors for X’s direct base classes and, if X is the type of the most derived class, 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. A return statement 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.
C++11 12.4 paragraph 10:
In an explicit destructor call, the destructor name appears as a ~ followed by a type-name or decltype-specifier that denotes the destructor’s class type. The invocation of a destructor is subject to the usual rules for member functions, ...
The example code in C++11 12.4 paragraph 10 indicates the intent of the above:
struct B {
virtual ~B() { }
};
struct D : B {
~D() { }
};
D D_object;
B* B_ptr = &D_object;
void f() {
D_object.B::~B(); // calls B’s destructor
B_ptr->~B(); // calls D’s destructor
...
}
master_latch, your example of using b->~Base(); is identical to the second call in the example code. Think of b->~Base(); as if it meant b->__destruct_me(). It is in a sense no different than a call to any other virtual function.
A compliant implementation has to do this because "because the standard says so." How an implementation does it? The standard doesn't say. (That's good requirementese, by the way. Say what has to be done, but don't say how to do it.)
Most implementations (every implementation I have poked into) do this by generating multiple functions for a destructor. One function implements the body of the destructor as specified by the programmer. A wrapper destructor executes this body of the destructor function, then destroys non-static data members in reverse order of construction, and then invokes parent class destructors. That classes can virtually inherit from some parent class adds another twist. This means that a third destructor function for a given class might be needed.
So how does an implementation know that b->~Base() should call the wrapper destructor for class Derived? Dynamically casting a pointer to a polymorphic class to a void* pointer yields a pointer to the most derived object.
C++11 5.2.7 paragraph 7:
If T is “pointer to cv void,” then the result is a pointer to the most derived object pointed to by v. Otherwise, a run-time check is applied to see if the object pointed or referred to by v can be converted to the type pointed or referred to by T.
In other words, dynamically casting a polymorphic pointer to void* yields a pointer to the object as it was declared or allocated. The virtual table (not a part of the standard) dictates how to find the destructor. The implementation ensures that the pointer to the virtual table can be determined from a void* pointer to the most derived object. This is what lets the implementation know which destructor to call. From that point on, the pointer to that most derived object is no longer a void* pointer.
Suppose that I have a base class pointer, with base class having virtual functions. And if I am pointing a derived class object using base class pointer then how compiler knows that it is derived version of that virtual function to be called since at the time of assignment the derived class address would have been converted into base class type, why doesn't compiler generate an error since memory layout of both may be different.
And also if I have declared base class destructor virtual and deleting the base pointer having address of derived class then how does compiler know that I am actually deleting the derived object.
class a{
public:
virtual ~a(){}
virtual void f(){}
};
class b:public a
{
public:
~b(){}
void f(){ cout<<"hi";}
};
main()
{
a *aptr;
aptr=new b; //here aptr has the address of b;
delete aptr; //since pointer type is base class so how will compiler know that
//it has to call derived's destructor,also their names are different
//as one is a and another is b.
}
To actually delete a derived class through a base pointer you need to declare the destructor virtual. Otherwise havoc will ensue (actually undefined behavior, which is about the same).
As for how virtual functions are implemented: it is up to the implementation. Without asking about a specific implementation a real answer is not possible. The most likely implementation are vtables.
It won't (or it will). It's undefined behavior deleting an object of derived type through a pointer to a base type without a virtual destructor.
I had this question (beginner C++) in a C++ quiz : My answer was incorrect, I want to understand the explanation behind the correct answer - "Undefined behavior"
Question:
What will happen in the following code after the function foo() returns?
class base
{
public:
base() { }
~base() { }
};
class derived : public base
{
private:
int *p_pi_values;
public:
derived() : p_pi_values(new int[100]) { }
~derived() { delete [] p_pi_values; }
};
void foo(void)
{
derived *p_derived = new derived();
base *p_base = p_derived;
// Do some other stuff here.
delete p_base;
}
I gave this answer which turned out wrong ==> integer array will not be properly deleted.
Correct Answer ==> The behavior is undefined.
The destructor of your base class isn't virtual. It's simply a rule of the language that if you delete an object through a pointer to a base subobject, the corresponding base class must have a virtual destructor, or otherwise it is undefined behaviour.
(In practice, if your base class doesn't have a virtual destructor, the compiler may not emit the necessary code to perform all the necessary clean-up for the derived object. It will just assume that your object is of the same type as the pointer and not bother to look further, as indeed the polymorphic lookup of the most derived object comes at a cost that you don't want to impose needlessly.)
§5.3.5/3:
In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined
You should make your destructor virtual in a base class. The problem with the code as it is now is that delete p_base will cause a destructor of base class to be called. The one from the derived class won't be called and the memory allocated for the array of integers won't be freed.
This happens because if a method isn't virtual in a base class, compiler simply looks at a pointer type and calls a method located in this type (in this case - it's a base class) i.e. a decision what method to call is made during compilation time based on the type of the pointer and not the real type of the object the pointer is referring to.
Out of curiousity I check the C++ specs. The answer to the question is item 3 in section 5.3.5:
In the first alternative (delete object), 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.
Personally, I would have answered the same way you did. If you ignore the compiler's warning, the most likely outcome is that the destructor of the derived class won't get called.
I guess compiler is allowed to optimize this code and hence the assignment of p_derived to p_base never happens.
To be more specific the compiler may optimize the code to one line.
delete new derived();
Hence it is viewed that the behavior as undefined as this can change how the compiler really optimizes the code.
C++ type change during deletion
I've read that when you construct a derived type, the type changes depending on which constructor is being called. So, if you create a derived object and call a virtual function using a base pointer, normally it would map to the implementation in the derived class. If you called the virtual function in the base class constructor though, it would use the base class implementation as the type of the object is technically that of the base class while in that function. For example (makeshift code, sorry if it doesn't compile):
class Base {
Base()
{
std::cerr << "Base Constructor.";
func();
}
virtual void func() {
std::cerr << "Func base called." << std::endl;
}
};
class Derived : public Base {
Derived()
{
std::cerr << "Derived Constructor.";
func();
}
void func() {
std::cerr << "Func derived called." << std::endl;
}
};
int main() {
Derived* d = new Derived;
delete d;
}
Should output:
Base Constructor.
Func base called.
Derived Constructor.
Func derived called.
First of all, is this always true or is it implementation dependent?
If I used RTTI and typeinfo, would the type printed in the base actually be that of the base, or is this more of an unwritten rule sort of situation?
Is it dangerous to call virtual functions from constructors with this in mind, or is it safe as long as you know what you're doing?
To keep it short and simple, you can have a Rule:
The virtual mechanism is disabled in Constructors and Destructors
A virtual function call in Base class will always call the base class version of the function, the same in derived class results in call to the Derived class version of the function.
First of all, is this always true or is it implementation dependent?
Yes this is always true. This is not implementation-dependent.
If I used RTTI and typeinfo, would the type printed in the base actually be that of the base?
Yes it would be of Base; Derived object doesn't even exist while you are in Base class constructor.
Is it dangerous to call virtual functions from constructors with this in mind, or is it safe as long as you know what you're doing?
No it is not dangerous to call virtual functions from constructor as long as you understand the semantics behind it.
This C++ FAQ should be a good read for you.
It's well-defined.
[n3290: 12.7/4]: Member functions, including virtual functions
(10.3), can be called during construction or destruction (12.6.2).
When a virtual function is called directly or indirectly from a
constructor or from a destructor, including during the construction or
destruction of the class’s non-static data members, and the object to
which the call applies is the object (call it x) under construction or
destruction, the function called is the final overrider in the
constructor’s or destructor’s class and not one overriding it in a
more-derived class. If the virtual function call uses an explicit
class member access (5.2.5) and the object expression refers to the
complete object of x or one of that object’s base class subobjects but
not x or one of its base class subobjects, the behavior is undefined.
There is an excellent article from Scott Meyers. It is from his book Effective C++.
The article can be found at:
Never Call Virtual Functions during Construction or Destruction
It also discusses an alternative implementation.
Recently I had a similar problem which I solved this way:
class EthernetFrame
{
protected:
/** ctor to be called from derived classes */
EthernetFrame(unsigned inPayloadLength)
{
calculatePadBytes(inPayloadLength);
}
private:
/** calculates needed required PadBytes for Frames < 64B
* #param inPayloadLength we need to know the length of the actual L3 frame
*/
void calculatePadBytes(unsigned inPayloadLength);
};
class IPv4Frame : public EthernetFrame
{
public:
/** create empty IPv4 packet */
IPv4Frame() :
EthernetFrame(cIPv4_MINIMUM_LENGTH)
{};
// IPv4 header + trailer in bytes
unsigned cIPv4_MINIMUM_LENGTH;
protected:
/** ctor to be called from derived classes */
IPv4Frame(unsigned inPayloadLength) :
EthernetFrame(cIPv4_MINIMUM_LENGTH+inPayloadLength)
{};
};
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.