I understand why this is happening, but I'm stuck trying to resolve it...here is what my code is doing when the error is generated (thus, leading to a crash) when my program exits...
pure virtual method called
SomeClass::~SomeClass()
{
BaseClassObject->SomePureVirtualMethod(this);
}
void DerivedClass::SomePureVirtualMethod(SomeClass* obj)
{
//Do stuff to remove obj from a collection
}
I never have a call to new SomeClass but I have a QList<SomeClass*> which I append SomeClass* objects to. The purpose of this destructor in SomeClass is to tell DerivedClass to remove a specific instance of SomeClass from it's collection of QList<SomeClass*>.
So, in a concrete example...
BaseClass = Shape
DerivedClass = Triangle
SomeClass = ShapeProperties which owns a reference to Shape
So, I never have a call to new ShapeProperties but I have a QList<ShapeProperties*> inside of Triangle. The destructor in ShapeProperties is to tell Triangle to remove a specific property of ShapeProperties from it's collection of QList<ShapeProperties*>.
By the time your destructor is called, the destructor of inherited classes has already been called. Within constructors and destructors, the dynamic type of the object can effectively be considered to be the same as the static type. That is, when you call virtual methods from within your constructors/destructors it's not the overriden versions of them that are called.
If SomePureVirtualMethod needs to be called at the destructor, then you will have to call it within the destructor of the class where the actual definition of the method you want is.
When you call the virtual method in the destructor of the Base class SomeClass it calls the method(SomePureVirtualMethod()) of the Base class SomeClass which is a pure virtual method with no definition. And hence the error.
Why does this happen?
The type of this in constructor or destructor is of the type whose constructor or destructor is being called and hence dynamic dispatch doesn't work in constructors and destructors as you would expect it to work in all other functions.
Why does it crash?
Because calling a pure virtual function from constructor or destructor is an Undefined Behavior.
C++03 10.4/6 states
"Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined."
How to avoid it?
Just ensure that you don't call a pure virtual function from constructor or destructor.
Don't call virtual methods in constructor or destructor unless you understand the dynamics involved.
There is another reason why this might happen, depending on your compiler and system, and that is from a dangling reference. Paul S. R. Chisholm explains the possible state of freed memory:
The memory might be marked as deallocated.
The memory might be deliberately scrambled.
The memory might be reused.
The memory might have been left exactly the way it was.
The last is an interesting case. What was the object "exactly the way
it was"? In this case, it was an instance of the abstract base class;
certainly that's the way the vtbl was left. What happens if we try to
call a pure virtual member function for such an object?
"Pure virtual function called".
Related
I'm having trouble understanding what's the reason for the crash in the following code :
class A {
public:
virtual ~A() { goo(); }
void goo() { absFoo(); }
virtual void absFoo() = 0;
};
class B : public A {
public:
void absFoo() { cout << "In B \n"; }
};
int main()
{
B b1;
b1.goo();
}
The main prints "In B" as expected, but in the end when it crashes, I can't debug it either, the compiler pops a weird message.
So my question is, when the destructor of A calls "goo()", does "absFoo()", crash
because we're referring to an abstract function?
Or does the compiler actually look for a definition in the derived classes? (And it doesn't exist anymore because it was destructed beforehand so it crashes)
I know that if we had called "absFoo()" directly from the destructor, the reason would have been the abstract function. But since here it's an outside function calling "absFoo()" I'm having trouble understanding the real reason.
What happens when a destructor calls an abstract function
First, let us consider what happens when a destructor calls any virtual function (the same applies to the constructor by the way): When a virtual function foo is called in the destructor of T, the call will not be dispatched dynamically to an implementation in a derived type (the lifetime of any derived object has already ended), but statically to the implementation T::foo.
If T::foo is pure virtual, then calling it without dynamic dispatch will have undefined behaviour. That is what happens when a pure virtual function is (indirectly) called in a destructor (or constructor).
Just to complement the already accepted answer, this is the documentation from cppreference.
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, e.g. in a member
initializer list), and the object to which the call applies is the
object 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.
In other words, during construction or destruction, the more-derived classes do not exist.
As the object is deconstructed, the vtable is updated to match the new status of the object.
Since you've removed the last function, the compiler will do whatever it considers fit; which in the case of a debug compilation in visual studio, will fallback to an abort reporting that a pure virtual function was called.
The vtable however is not part of the standard, it's an implementation detail, and there's no requirement for your program to crash; it's just what is considered the nicest thing to do when you've called a pure virtual function.
I was trying to familiarize myself with the OOP concepts but could not quite understand the concept of virtual.
One can create a virtual destructor but not a virtual constructor. Why?
How are virtual destructors handled internally? I mean the link Virtual Destructors illustrates the concept but my question is how the vptr of both the vtables (Derived and Base) are called? (In case of virtual member functions when such a scenario occurs generally the function that vptr of Derived class points to is only called)
Are there any other scenarios where one may need to use a virtual destructor?
Can anyone please help me understand the above concepts with links/examples?
First, a little about the difference between virtual functions and non-virtual functions:
Every non-virtual function-call that you have in your code can be resolved during compilation or linkage.
By resolved, we mean that the address of the function can be computed by the compiler or the linker.
So in the object code created, the function-call can be replaced with an op-code for jumping to the address of that function in memory.
With virtual functions, you have the ability to invoke functions which can be resolved only during runtime.
Instead of explaining it, let's run through a simple scenario:
class Animal
{
virtual void Eat(int amount) = 0;
};
class Lion : public Animal
{
virtual void Eat(int amount) { ... }
};
class Tiger : public Animal
{
virtual void Eat(int amount) { ... }
};
class Tigon : public Animal
{
virtual void Eat(int amount) { ... }
};
class Liger : public Animal
{
virtual void Eat(int amount) { ... }
};
void Safari(Animal* animals[], int numOfAnimals, int amount)
{
for (int i=0; i<numOfAnimals; i++)
animals[i]->Eat(amount);
// A different function may execute at each iteration
}
As you can probably understand, the Safari function allows you to be flexible and feed different animals.
But since the exact type of each animal is not known until runtime, so is the exact Eat function to be called.
The constructor of a class cannot be virtual because:
Calling a virtual function of an object is performed through the V-Table of the object's class.
Every object holds a pointer to the V-Table of its class, but this pointer is initialized only at runtime, when the object is created.
In other words, this pointer is initialized only when the constructor is called, and therefore the constructor itself cannot be virtual.
Besides that, there is no sense for the constructor to be virtual in the first place.
The idea behind virtual functions is that you can call them without knowing the exact type of the object with which they are called.
When you create an object (i.e., when you implicitly call a constructor), you know exactly what type of object you are creating, so you have no need for this mechanism.
The destructor of a base-class has to be virtual because:
When you statically allocate an object whose class inherits from the base-class, then at the end of the function (if the object is local) or the program (if the object is global), the destructor of the class is automatically invoked, and in turn, invokes the destructor of the base-class.
In this case, there is no meaning to the fact that the destructor is virtual.
On the other hand, when you dynamically allocate (new) an object whose class inherits from the base-class, then you need to dynamically deallocate (delete) it at some later point in the execution of the program.
The delete operator takes a pointer to the object, where the pointer's type may be the base-class itself.
In such case, if the destructor is virtual, then the delete operator invokes the destructor of the class, which in turn invokes the destructor of the base-class.
But if the destructor is not virtual, then the delete operator invokes the destructor of the base-class, and the destructor of the actual class is never invoked.
Consider the following example:
class A
{
A() {...}
~A() {...}
};
class B: public A
{
B() {...}
~B() {...}
};
void func()
{
A* b = new B(); // must invoke the destructor of class 'B' at some later point
...
delete b; // the destructor of class 'B' is never invoked
}
One can create a virtual destructor but not a virtual constructor. Why?
Virtual functions are dispatched according to the type of the object they're called on. When a constructor is called, there is no object - it's the constructor's job to create one. Without an object, there's no possibility of virtual dispatch, so the constructor can't be virtual.
How are virtual destructors handled internally?
The internal details of virtual dispatch are implementation-defined; the language doesn't specify the implementation, only the behaviour. Typically, the destructor is called via a vtable just like any virtual function.
how the vptr of both the vtables (Derived and Base) are called?
Only the most-derived destructor will be called virtually. All destructors, virtual or not, will implicitly call the destructors of all member and direct base-class subobjects. (The situation is slightly more complicated in the presence of virtual inheritance; but that's beyond the scope of this question).
Are there any other scenarios where one may need to use a virtual destructor?
You need one in order to support polymorphic deletion; that is, to be able to delete an object of derived type via a pointer to a base type. Without a virtual destructor for the base type, that's not allowed, and will give undefined behaviour.
because a Virtual function is invoked at runtime phase, however constructors are invoked at initialization phase, object is not constructed. So it's meaningless to have a virtual constructor.
a. the reason why only the base class desctructor is invoked in your link, the destructor is not marked as virtual, so the desctructor address is linked to Base class destructor at compile/link time, and obviously the type of the pointer is Base instead of Derived at compile time.
b. for why both of Base and Derived constructors are invoked after adding virtual to Base desctructor. It's same behavior like below:
Derived d; // when d exits the lifecycle, both Derived and Base's desctructor will be invoked.
Suppose when you have at least one virtual function, you should have a virtual desctructor.
One can create a virtual destructor but not a virtual constructor.
Why?
I'll try and explain this in layman's terms.
A class in c++ only exists after it's constructor completes. Each base class exists prior to initialisation of derived class and its members (vtable links included). Hence, having a virtual constructor does not make sense (since to construct, you need to know the type). Furthermore (in c++), calling virtual functions from a constructor does not work (as the derived class's vtable part has not been set up). If one thinks about it carefully, allowing virtual functions to be called from a contructor opens up a can of worms (such as what if virtual functions of derived classes are called prior to member initialization).
As far as destructors are concerned, at the point of destruction, the vtable is "intact", and we (c++ runtime) are fully aware of the type (so to speak). The destructor of the most derived part of the type is found (if virtual, through vtable), and therefore that destructor, and naturally that of all bases can be called.
How are virtual destructors handled internally? I mean the link
Virtual Destructors illustrates the concept but my question is how the
vptr of both the vtables (Derived and Base) are called?
Destructors are handled the same as normal virtual functions (that is, there addresses are looked up in a vtable if they are virtual at the expense of one (perhaps 2?) extra level/s of indirection). Furthermore, c++ guarantees that all base destructors shall execute (in opposite order of construction which relies on order of declaration) after completion of a derived destructor.
One can mimick/simulate virtual construction by using patterns such as the prototype pattern (or cloning), or by using factories. In such cases either an instance of the real type exists (to be used polymorphically), or a factory exists (deriving from abstract factory), that creates a type (via virtual function) based on some knowledge provided.
Hope this helps.
I assume we have a Base class A, and it's derived B.
1.: You can delete B via an A pointer, and then the correct method is to call the B destructor too.
However, you just can't say, that a B object should be created while you actually just call the A constructor. There is just not such a case.
You can say:
A* a = new B ();
or
B b;
But both directly call the B's constructor.
2.: Well, i am not entirely sure, but i guess it will iterate through the relevant part of the class hierarchy, and search for the closest call of the function. If a function is not virtual, it stop iterating and call it.
3.: You should always use virtual destructor, if you want to inherit something from that class. If it's a final class, you shouldn't.
I wasted a couple of days trying to discover why my derived virtual destructors were not being called before discovering the answer so hopefully I can save other a lot of grief with this reply.
I started using derived classes three and four levels deep in my project. Virtual functions seemed to work fine but then I discovered I had massive memory leaks because my destructors were not being called. No compiler or runtime error - the destructors just were not being called.
There is a ton of documentation and examples about this on the web but none of it was useful because my syntax was correct.
I decided that if the compiler wasn't going to call my destructors, I needed to create my own virtual destruct method to call. Then I got the compiler error that solved the problem - "class if a Forward Reference". Adding an include for the derived class header files in the base class solved the problem. The compiler needs the class definition to call the destructor!
I suggest when creating a new derived class, include the header file in the base and intermediate classes. Probably also a good idea to add conditional debug code to your destructors to check that they are bing called.
Bob Rice
I will type an example :
class A
{
public:
virtual ~A(){}
};
class B: public A
{
public:
~B()
{
}
};
int main(void)
{
A * a = new B;
delete a;
return 0;
}
Now in Above Example , destructors will be called recursively bottom to up .
My Question is how Compiler do this MAGIC .
There are two different pieces of magic in your question. The first one is how does the compiler call the final overrider for the destructor and the second one is how does it then call all the other destructors in order.
Disclaimer: The standard does not mandate any particular way of performing this operations, it only mandates what the behavior of the operations at a higher level are. These are implementation details that are common to various implementations, but not mandated by the standard.
How does the compiler dispatch to the final overrider?
The first answer is the simple one, the same dynamic dispatch mechanism that is used for other virtual functions is used for destructors. To refresh it, each object stores a pointer (vptr) to each of its vtables (in the event of multiple inheritance there can be more than one), when the compiler sees a call to any virtual function, it follows the vptr of the static type of the pointer to find the vtable and then uses the pointer in that table to forward the call. In most cases the call can be directly dispatched, in others (multiple inheritance) it calls some intermediate code (thunk) that fixes the this pointer to refer to the type of the final overrider for that function.
How does the compiler then call the base destructors?
The process of destructing an object takes more operations than those you write inside the body of the destructor. When the compiler generates the code for the destructor, it adds extra code both before and after the user defined code.
Before the first line of a user defined destructor is called, the compiler injects code that will make the type of the object be that of the destructor being called. That is, right before ~derived is entered, the compiler adds code that will modify the vptr to refer to the vtable of derived, so that effectively, the runtime type of the object becomes derived (*).
After the last line of your user defined code, the compiler injects calls to the member destructors as well as base destructor(s). This is performed disabling dynamic dispatch, which means that it will no longer come all the way down to the just executed destructor. It is the equivalent of adding this->~mybase(); for each base of the object (in reverse order of declaration of the bases) at the end of the destructor.
With virtual inheritance, things get a bit more complex, but overall they follow this pattern.
EDIT (forgot the (*)):
(*) The standard mandates in §12/3:
When a virtual function is called directly or indirectly from a constructor (including from the mem-initializer for a 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 con- structor or destructor’s class, or overriding it in one of the other base classes of the most derived object.
That requirement implies that the runtime type of the object is that of the class being constructed/destructed at this time, even if the original object that is being constructed/destructed is of a derived type. A simple test to verify this implementation can be:
struct base {
virtual ~base() { f(); }
virtual void f() { std::cout << "base"; }
};
struct derived : base {
void f() { std::cout << "derived"; }
};
int main() {
base * p = new derived;
delete p;
}
A virtual destructor is treated in the same way as any other virtual function. I note that you've correctly maked the base class's destructor as virtual. As such, it is no way different than any other virtual function, as far as dynamic dispatch is concerned. The most derived class destructor gets called through dynamic dispatch but it also automatically results in calls to Base class destructors of the class1.
Most compiler implements this feature using vtable and vptr, though the language specification does not mandate it. There can be a compiler which does this differently, without using vtable and vptr.
Anyway, as it true for most compilers, it is worth knowing what vtable is. So vtable is a table contains pointers of all virtual functions the class defines, and the compiler adds vptr to the class as hidden pointer which points to the correct vtable, so the compiler uses correct index, calculated at compile-time, to the vtable so as to dispatch the correct virtual function at runtime.
1. The italicized text is taken from #Als's comment. Thanks to him. It makes things more clear.
A suitable implementation of (virtual) destructors the compiler might use would be (in pseudocode)
class Base {
...
virtual void __destruct(bool should_delete);
...
};
void Base::__destruct(bool should_delete)
{
this->__vptr = &Base::vtable; // Base is now the most derived subobject
... your destructor code ...
members::__destruct(false); // if any, in the reverse order of declaration
base_classes::__destruct(false); // if any
if(should_delete)
operator delete(this); // this would call operator delete defined here, or inherited
}
This function gets defined even if you didn't define a destructor. Your code would just be empty in that case.
Now all derived classes would override (automatically) this virtual function:
class Der : public Base {
...
virtual void __destruct(bool should_delete);
...
};
void Der::__destruct(bool should_delete)
{
this->__vptr = &Der::vtable;
... your destructor code ...
members::__destruct(false);
Base::__destruct(false);
if(should_delete)
operator delete(this);
}
A call delete x, where x is of pointer to class type, would be translated as
x->__destruct(true);
and any other destructor call (implicit due to variable going out of scope, explicit x.~T()) would be
x.__destruct(false);
This results in
the most derived destructor always being called (for virtual destructors)
operator delete from the most derived object being called
all members' and base classes' destructors being called.
HTH. This should be understandable if you understand virtual functions.
As usual with virtual functions there will be some implementation mechanism (like a vtable pointer) that will let the compiler find which destructor to run first depending on the type of the object. Once the most derived class destructor is run it will in turn run the base class destructor and so on.
It's up to the compiler how to implement it and typically it's done with the same mechanism as other virtual methods. In other words there's nothing special about destructors that requires a virtual method dispatch mechanism that is distinct from that used by normal methods.
A virtual destructor has an entry in the virtual table just as other virtual functions do. When the destructor is invoked -either manually or automatically from a call to delete- the most derived version is invoked. A destructor also automatically calls the destructor for its base classes, so that in combination with the virtual dispatch is what causes the magic.
Unlike other virtual functions, when you override a virtual destructor, your object's virtual destructor is called in addition to any inherited virtual destructors.
Technically this can be achieved by whatever means the compiler chooses, but almost all compilers achieve this via static memory called a vtable, which permits polymorphism on functions and destructors. For each class in your source code, a static constant vtable is generated for it at compile time. When an object of type T is constructed at runtime, the object's memory is initialized with a hidden vtable pointer which points to the T's vtable in ROM. Inside the vtable is a list of member function pointers and a list of destructor function pointers. When a variable of any type that has a vtable goes out of scope or is deleted with delete or delete[], all of the destructor pointers in vtable the object points to are all invoked. (Some compilers choose to only store the most derived destructor pointer in the table, and then include a hidden invocation of the superclass's destructor in the body of every virtual destructor if one exists. This results in equivalent behavior.)
Additional magic is needed for virtual and nonvirtual multiple inheritance. Assume I am deleting a pointer p, where p is of the type of a base-class. We need to invoke the destructor of the sub-classes with this=p. But using multiple inheritance, p and the start of the derived object may not be the same! There is a fixed offset which must be applied. There is one such offset stored in the vtable for each class that is inherited, as well as a set of inherited offsets.
When you have a pointer to an object, it points to a block of memory that has both the data for that object and a 'vtable pointer.' In microsoft compilers, the vtable pointer is the first piece of data in the object. In Borland compilers, it is the last. Either way, it points to a vtable that represents a list of function vectors corresponding to the virtual methods that can be invoked for that object/class. The virtual destructor is just another vector in that list of function pointer vectors.
If I have a base class and a derived class, and I delcare the destructor in the parent virtual, but instantiate an object of type subclass, when destroyed it will invoke the parent destructor right(since virtual)? If I also declare a destructor in the derived class, will it call both destructors (base and derived). Thanks in advance :-).
The second part to my question is regarding the first. Why does the base class destructor need to be declared virtual. Don't constrcutors cycle up the hiearchy. They don't share the same name, so where's the need for it? Shouldn't it work the same for destrucotrs, or by default is only one called? Also does through late binding is it able to detect all the classes and object is made of?
EDIT: My question is not just about virtual destructors, but why does it need to be declared virtual, since they should all be called by default.
Yes, parent destructors will be called automatically.
The destructor should be virtualised so a derived instance can be destroyed properly by code that thinks it has a reference to a base class instance.
In very limited circumstances, it is OK not to virtualise, if you really need to save a few cycles on the vtable lookup.
The need for virtual destructors is because of polymorphism. If you have something like the following:
class A { ... };
class B : public A { ... };
void destroy_class(A* input)
{
delete input;
}
int main()
{
B* class_ptr = new B();
destroy_class(class_ptr); //you want the right destructor called
return 0;
}
While a bit of a contrived example, when you delete the passed-in pointer for the destroy_class() function, you want the correct destructor to get called. If the destructor for class A was not declared virtual, then only the destructor for class A would get called, not the destructor for class B or any other derived type of class A.
Stuff like this is very often a fact-of-life with non-template polymorphic data-structures, etc. where a single deletion function may have to delete pointers of some base-class type that actually points to an object of a derived type.
rubixibuc,
Yeah the subclasses destructor is invoked first, then it's superclass... then it's superclass, and so on until we get to Object's destructor.
More here: http://www.devx.com/tips/Tip/13059 ... it's worth the read... only a screen-full, but it's an INFORMATIVE screen-full.
Inspired by: C++ -- why should we define the pure virtual destructor outside the class definition?
What does the following code actually do?
class Object
{
public:
virtual ~Object() = 0;
};
Object::~Object() { /*...*/ }
I thought that the point of a pure virtual function was to force subclasses to implement that particular function. If that is the case, then why bother implementing the same function in the virtual base class?
This code prevents you from creating an instance of Object, while at the same time allowing you to create subclasses.
When destroying an object, the destructor of the parent class will be called, so it must exist. This applies whether the destructor is pure virtual or not. A pure virtual member function only needs to be defined if you explicitly call it, Foo:theFunc().
In the case of a pure virtual destructor, there is no way of 'forcing' anyone to implement it in derived classes. The compiler will write one for you. In addition, the compiler written destructor (in a derived class) will call the parent destructor - so you had better have written an implementation for the parent.
So, to summarise:
A pure virtual function that is not a destructor need not have an implementation as you would not expect a programmer to call it.
A pure virtual destructor must have an implementation since the compiler is bound to call it from destructors (both programmer and compiler written) in child classes.