Destructor concept in c++ - c++

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;
}

Related

The constructor of base class is not called by derived class when base class pointer is used

Why the base class constructor is not called twice in the following code?
#include<iostream>
using namespace std;
class base{
public:
base(){cout << "In the Base Constructor\n"; }
~base(){
cout << "In Base Destructor\n";
}
};
class derived: public base{
public:
derived(){cout << "In Derived Constructor\n";}
~derived(){
cout << "In Derived Destructor\n";
}
};
int main(){
base *bptr;
derived d;
}
output:
In the Base Constructor
In Derived Constructor
In Derived Destructor
In Base Destructor
It must be because of the pointer. But I am not clear why?
This is a pointer to something.
base *bptr;
It is not initialised.
It does not point to anything clean.
It especially does not point to any already created object.
Even if it did, that would not cause any constructor to be executed.
If there would be any object the pointer points to, then the creation of that object would have happened elsewhere, earlier.
This defines an object:
derived d;
This is what causes the observed execution of constructors.

A misunderstanding with polymorphism and virtual destructors

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)

c++ abstract classes constructor calls

Can anyone explain to me the constructor calls, in the following code.
How is the constructor of abstract class called, when there exist no object for it but only a pointer to the derived class. Is an instance of it created to hold the vtable ?
#include <iostream>
using namespace std;
class pure_virtual {
public:
pure_virtual() {
cout << "Virtul class constructor called !" << endl;
}
virtual void show()=0;
};
class inherit: public pure_virtual {
public:
inherit() {
cout << "Derived class constructor called !" << endl;
}
void show() {
cout <<"stub";
}
};
main() {
pure_virtual *ptr;
inherit temp;
ptr = &temp;
ptr->show();
}
The constructor of the pure_virtual class is called when the constructor of inherit is called. So, when the line inherit temp; is executed, the constructor of the object is being called, because it is a derived class. Then the base class constructor is called first.
So in your case the output will be
Virtul class constructor called !
Derived class constructor called !
and because the void show() is virtual, the correct function is called, which is that of the inherit class.

Protected non-virtual destructor in the 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.

Scope of pure virtual functions during derived class destruction - In C++

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.