During destruction of the derived class object, i first hit the derived class destructor and then the base class destructor (which is as expected). But i was curious to find out - at what point does the functions of the derived class go out of scope (are destroyed).
Does it happen as soon as the control leaves the derived class destructor and goes toward the base? Or does it happen once we done with the base class destructor also.
Thanks
Once the destructor of the most derived class finishes, the dynamic type of the object can be considered that of the next less-derived-type. That is, a call to a virtual method in the base destructor will find that the final overrider at that point in time is at base level. (The opposite occurs during construction)
struct base {
base() { std::cout << type() << std::endl; }
virtual ~base() { std::cout << type() << std::endl; }
virtual std::string type() const {
return "base";
}
};
struct derived : base {
virtual std::string type() const {
return "derived";
}
};
int main() {
base *p = new derived;
std::cout << p->type() << std::endl;
delete p;
}
// output:
// base
// derived
// base
Functions don't get destroyed.
Virtual functions however get their entry in the v-table erased as soon as the derived destructor finishes so you can't call derived virtual functions from the base d'tor.
Related
Example:
class Base {
public:
virtual void f() = 0;
virtual ~Base() { std::cout << "Base::~Base()\n"; }
};
class Derived : public Base {
public:
void f() { }
~Derived() { std::cout << "Derived::~Derived()\n"; }
};
int main() {
Base* p = new Derived();
delete p;
return 0;
}
Output:
Derived::~Derived()
Base::~Base()
I thought only the derived class destructor will be called since the pointed object to be freed is an instance of the derived class.
I have two questions:
Why was the virtual base destructor called?
Is it legally possible (or should it even be possible) to prevent the base class destructor from being called?
Why was the virtual base destructor called?
Because base class should be properly destructed. Derived class can not possibly do this.
Is it legally possible (or should it even be possible) to prevent the
base class destructor from being called?
No, because it would prevent properly destructing the base class (i.e. call it's members destructors)
What is the derived class doing in this code like:
class Base
{
public:
virtual std::string Name(){ return "Base Class"}
};
class Derived : public Base
{
public:
std::string Name() {return "Derived Class"}
}
int main()
{
Base* object = new Derived();
return 0;
}
I was following a tutorial but didn't understand What does Derived class in The instantiation of Base Class was doing in the above code.
The goal is to implement polymorphism, it's a OOP concept which allows you, among other things, to make derived class methods override the base class.
Consider the following:
class Base {
public:
//virtual keyword allows method to be overriden
virtual std::string Name() { return "Base Class"; }
//virtual destructor needed for polymorphism otherwise it can lead to undefined behavior
virtual ~Base(){}
};
class Derived : public Base {
public:
//optional keyword override signal the method has been overriden
std::string Name() override { return "Derived Class"; }
};
class Derived2 : public Base {
public:
std::string Name() override { return "Derived Class 2"; }
};
int main() {
Base *object = new Derived();
Base *object2 = new Derived2();
Base *object3 = new Base();
//collection of objects of type Base* which can hold any class of the family
Base *collection[] = {object, object2, object3};
for (auto &obj : collection) {//test print
std::cout << obj->Name() << std::endl;
}
}
As the comments explain, I can have a collection of different objects of the same family and when you call Name() the method call will deppend on the object.
Output:
Derived Class
Derived Class 2
Base Class
modifying main to be :
int main()
{
Base* object = new Derived();
std::cout << object->Name() << std::endl;
return 0;
}
and adding 3 missing ';' in your code, you will see that writes Derived Class, the called method Name is the one of the real type of object being Derived.
Note while Name is virtual in Base it is also in Derived even you do not said explicitly.
virtual allows to use the real type of an object when you apply an method on, so even object is declared Base when Name is virtual the called version is the one of the real type being Derived
But if you remove virtual in the definition of Name in Base that writes Base Class because object being declared Base the called method is Name defined on Base.
The result will be the same adding virtual on Derived but still removing it on Base, because for the compiler object being declared Base and Name being not virtual on Base that one is called without considering the real type of object
So, having :
#include <iostream>
#include <string>
class Base
{
public:
virtual std::string virtualName(){ return "Base Class";}
std::string nonVirtualName(){ return "Base Class";}
};
class Derived : public Base
{
public:
std::string virtualName() {return "Derived Class";} // implicitely virtual
std::string nonVirtualName(){ return "Base Class";}
};
int main()
{
Base* object = new Derived();
std::cout << object->virtualName() << std::endl;
std::cout << object->nonVirtualName() << std::endl;
return 0;
}
Compilation and execution :
bruno#bruno-XPS-8300:/tmp$ g++ -Wall a.cc
bruno#bruno-XPS-8300:/tmp$ ./a.out
Derived Class
Base Class
bruno#bruno-XPS-8300:/tmp$
Note if you add delete object; at the end of main and because of the default destructor in not virtual the called destructor is the one of Base exactly for nonVirtualName and nothing is done for Derived. Defining the destructor virtual on Base is the right way to do, that implies the destructor is at least implicitly virtual on Derived allowing to have both destructors executed on delete object;
Example code:
#include <string>
namespace vehicle
{
class Vehicle
{
public:
Vehicle(int a);
virtual ~Vehicle(); <------ not method?
protected:
int a;
};
}
Also, I don't fully get the concept of a pure virtual method where you declare a method as:
virtual method() = 0;
Why do we need this?
Let's suppose there are two classes: Base and Derived
struct Base
{
Base() {}
virtual void foo() = 0;
virtual ~Base()
{
std::cout << "Base descructor" << std::endl;
}
};
struct Derived : Base
{
int *i;
Derived(int i_): Base(), i(new int[i_]) {}
virtual void foo() override
{
std::cout << "foo" << std::endl;
}
virtual ~Derived()
{
std::cout << "Derived descructor" << std::endl;
delete [] i;
}
};
Pure virtual functions
If Derived doesn't override the foo function you can create an instance of the Derived class. When you try, your code will not compile, because foo is a pure virtual function.
error: invalid new-expression of abstract class type 'Derived'
note: because the following virtual functions are pure within 'Derived':
struct Derived : Base
Pure virtual functions are used to describe the interface.
Now about virtual destructors:
The ~(tilda) sign is used to denote the class destructor. It
is a special method that is called when the object is destroyed.
A client creates an instance of Derived:
Base *instance = new Derived;
then this variable is used somehow and when you don't need the variable you need to free the memory:
delete instance;
Let's trace the calls:
Derived descructor
Base descructor
So you can see that both base and derived destructors are called and no memory leak is possible. But if you remove this virtual keyword from the destructors
Base descructor
As you can see the descturtor of Derived is not called, so a memory leak exists (the array of Derived class don't get released).
Hence virtual constructors are useful when you work with objects through pointers.
virtual ~Vehicle();
The tilde ~ denotes a destructor. It's a method, a special method for destroy the object.
Virtual destructor is used in abstract base class.
virtual method() = 0;
That's pure virtual function. It indicates that you have to provide implementation method for the implementation class implementing this abstract base class.
I am trying to understand virtual destructors. The following is a copy paste from this page When to use virtual destructors?
Here, you'll notice that I didn't declare Base's destructor to be
virtual. Now, let's have a look at the following snippet:
Base *b = new Derived(); // use b
delete b; // Here's the problem!
[...] If you want to prevent the deletion of an instance through a base class pointer, you can make the base class destructor protected and non-virtual; by doing so, the compiler won't let you call delete on a base class pointer.
I don't understand why the deletion is prevented by having a protected non-virtual base class destructor. Doesn't the compiler think that we're trying to call delete from a base class object? What does protected have to do with that?
The C++ Standard has this to say about delete (section 5.3.5p10):
Access and ambiguity control are done for both the deallocation function and the destructor (12.4, 12.5).
Therefore, only code that has access to the destructor is able to use delete. Since the destructor is protected, that means that no one can call delete on a pointer of type Base*. Only subclasses can use the destructor at all (and the only thing that will is the subclass's own destructor, as part of the subobject destruction process).
Of course, the subclass should make its own destructor public, allowing you to delete objects through the subclass type (assuming that is the correct actual type).
NOTE: Actually, other members of Base can do delete (Base*)p; since they have access. But C++ assumes that someone using this construct will not be doing that -- C++ access control only provides guidance to code outside your class.
delete b; effectively performs b->~Base(); deallocate(b);. The first part - calling the destructor - would fail to compile if the destructor is inaccessible (in the same way that calling any other inaccessible method fails).
From my understanding (based on this page), the only case we would like to use the non-virtual and protected destructor in the base class is the following:
#include <iostream>
struct unary_function {
protected:
~unary_function() {
std::cout << "unary_function" << std::endl;
}
};
struct IsOdd : public unary_function {
public:
bool operator()(int number) {
return (number % 2 != 0);
}
};
void f(unary_function *f) {
// compile error
// delete f;
}
int main() {
// unary_function *a = new IsOdd;
// delete a;
IsOdd *a = new IsOdd;
delete a;
getchar();
return 0;
}
therefore, you can only do this:
IsOdd *a = new IsOdd;
delete a;
or
IsOdd c;
never these:
unary_function *a = new IsOdd;
delete a;
therefore, with nonvirtual protected destructor, the compiler would give an error when you try to use this
void f(unary_function *f) {
delete f;
// this function couldn't get compiled because of this delete.
// you would have to use the derived class as the parameter
}
Protected methods and variables of a class (let's call it Base) can only be accessed by derived classes. Thus, if you call delete on a pointer of type Base outside a derived class, it will try to call Base::~Base() (Base's destructor), but since it is protected, it cannot be called, which thus results in a compilation error.
According to the specification, the destructor of a base class must only be declared protected and non-virtual (to not allow deletion of a derived object through a Base pointer), or public and virtual (to allow safe deletion of a derived object through a Base pointer).
If a destructor is declared public and non-virtual, it results in undefined behaviour if a pointer of type Base which points to a derived class is deleted.
The two options:
Non-virtual protected destructor - Base pointer to Derived cannot be deleted:
class Base {
public:
Base() {
std::cout << "Base ctor called.\n";
}
protected:
~Base() {
std::cout << "Base dtor called.\n";
}
};
class Derived : public Base {
public:
Derived() {
std::cout << "Derived ctor called.\n";
}
~Derived() {
std::cout << "Derived dtor called.\n";
}
};
Base *foo = new Derived;
delete foo; // compilation error
... as mentioned in your question.
Public virtual destructor - allows a pointer of type Base to a Derived object to be deleted. First the Derived destructor is called, and then the Base destructor is called:
class Base {
public:
Base() {
std::cout << "Base ctor called.\n";
}
virtual ~Base() {
std::cout << "Base dtor called.\n";
}
};
class Derived : public Base {
public:
Derived() {
std::cout << "Derived ctor called.\n";
}
~Derived() override {
std::cout << "Derived dtor called.\n";
}
};
Base *foo = new Derived;
delete foo;
Output:
Base ctor called.
Derived ctor called.
Derived dtor called.
Base dtor called.
please go through my below code:
#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
class ClassA
{
protected:
int width, height;
public:
void set_values(int x, int y)
{
width = x;
height = y;
}
virtual int area()
{
return 100;
}
~ClassA()
{
cout << "base class destructor called" << endl;
}
};
class ClassB : public ClassA
{
public :
int area()
{
return (width * height);
}
~ClassB()
{
cout << "derived class destructor called" << endl;
}
};
int main()
{
ClassA *Ptr = new ClassB;
Ptr->set_values(10, 20);
cout << Ptr->area() << endl;
delete Ptr;
return 0;
}
In the above code the pointer contain the address of derived class object so it should call derived class destructor along with base class destructor when i delete the pointer,but why it is calling only base class destructor. if i made base class destructor as virtual then it is calling both derived class and base class destructor why?. and in virtual functions case both the base and derived class has the same function name so compiler resolve the one which is most derived in the derived class but here the destructor won't have same name then how the compiler resolves which one it has to call during run time.please explain me how
You should make the destructor of your base class virtual in order for polymorphic destruction to work properly:
class ClassA
{
// ...
virtual ~ClassA()
// ^^^^^^^
// Add this!
{
cout << "base class destructor called" << endl;
}
};
If you do not do that, you get Undefined Behavior when doing delete Ptr.
if i made base class destructor as virtual then it is calling both derived class and base class destructor why?
This is part of the regular object destruction sequence. When you destroy an object, the destructor of that object's class gets called first, then the destructors of all the non-static class members of that object (in inverse order of declaration), then the destructors of all its base classes.
Thus, virtual dispatch is correctly performed here (if you make your base class destructor virtual, of course), in the sense that the first destructor that gets invoked is the destructor of the actual run-time type of your object (ClassB). After that, the destructor of the base class ClassA gets invoked as well as part of the normal destruction process.
but here the destructor won't have same name then how the compiler resolves which one it has to call during run time
Destructors are special member functions. Each class can have only one destructor, so their name (which must be identical to the name of the class, with the prepended ~ character) is irrelevant. The compiler knows which function is a destructor.
Because your Base class destructor should be virtual.
That's actually undefined behavior because ~ClassA() is not virtual, so anything can happen.
ClassA *Ptr = new ClassB;
///....
delete Ptr;
You need to mark your destructors as virtual. Otherwise the compiler doesn't know to call the most-derived destructor.
virtual ~ClassA()
{
cout << "base class destructor called" << endl;
}