Virtual Destructors and function chaining in C++

Virtual Destructor:-

  • As like a normal function we can create a destructor as virtual.
  • If the class contains at least a single virtual destructor then VPTR is created and it is initialized with appropriate v-table.
  • Virtual destructors are necessary if there is an inheritance and up casting concept is used.
  • If virtual destructors are not written then there is a chance of a memory leak.

e.g.

class base

{

public:

base()

{

cout<<”base class constructor.”;

}

~base()

{

cout<<”base class destructor.”;

}

};

class derived:public base

{

derived()

{

cout<<”derived class constructor.”;

}

~derived ()

{

cout<<”derived class destructor.”;

}

};

int main()

{

base *b = new derived();

delete b;

return0;

}

  • In this case, we are using up casting concept in which base class pointer is pointing to a derived class object whose memory is allocated on heap.
  • When we create an object of a derived class, first constructor of base class is called then constructor of derived class is called.
  • In this case, memory is allocated dynamically by keyword ‘new’ hence we have to delete it by using delete operator.
  • For delete, we pass pointer of a base class, due to which delete only deallocates a memory of a base class but still memory of a derived class is allocated and due to above problem memory of a derived class object is leaked and it generates a runtime problems for our program.
  • According to above, destructor of a base class is called.
  • Hence output of a program is,

base class constructor

derived class constructor

base class destructor

  • To overcome this problem we can create a virtual destructor inside a base class.
  • Due to this virtual destructor our empty class requires 4 bytes for storing address of a vtable.

e.g.

class base

{

public:

base()

{

cout<<”base class constructor”;

}

virtual ~base()

{

cout<<”base class destructor”;

}

};

class derived:public base

{

public:

derived()

{

cout<<”derived class constructor”;

}

~derived()

{

cout<<”derived class destructor”;

}

};

Output:-

base class constructor

derived class constructor

derived class destructor

base class destructor

  • When we write destructor of a base class then compiler first calls a destructor of a pointed object by base class pointer.
  • In this case, base class pointer is pointing to a derived class object due to which first destructor of derived class is called and destructor of base class is by default called.
  • The above effect is only applicable if there is an up casting concept otherwise there is no need to write virtual destructor.
  • But in standard C++ we have to use up casting in each and every scenario, hence to avoid a memory leak we have to provide virtual destructor.

c++ this pointer

 

Pure virtual destructor:-

  • As like a normal function we can write a pure virtual destructor.
  • If we write a single pure virtual function inside a class, we cannot create an object of that class and that class becomes an abstract class.
  • The same effect is achieved by writing pure virtual destructor means a class contains pure virtual destructor then we are unable to create an object of that class.
  • There is no use of writing pure virtual destructor.
  • If we write a normal pure virtual function in a base class then derived class must provide its definition. Otherwise compiler generates an error.
  • But the above problem is not occurred in a pure virtual destructor, because, if we do not provide a destructor definition in derived class then compiler provides its own definition for the derived class.

e.g.

class base

{

public:

base()

{

cout<<”base class constructor.”;

}

virtual ~base()=0;

};

base::~base()

{

cout<<”base class destructor.”;

}

class derived:public cbase

{

public:

derived()

{

cout<<”derived class constructor.”;

}

~derived()

{

cout<<”base class destructor.”;

}

};

int main()

{

base b; // error,because, we cannot create an object of an abstract class.

base *bp;

bp = new derived();

delete(bp);

return 0;

}

Output:-

In this example, all the constructor and destructor are called.

(In our example, base class becomes abstract class due to which we cannot call any method of a base class as well as we cannot create an object of that class.)

 

Function chaining:-

  • In C++, we can call a function in a chain. Means each function calls another function after its execution.
  • In this, there is no explicit call from the function.

e.g.

class demo

{

public:

demo fun()

{

cout<<”fun of demo class”;

return *this;

}

demo gun()

{

cout<<”gun of demo class”;

return *this;

}

demo sun()

{

cout<<”sun of demo class”;

return *this;

}

void mun()

{

cout<<”mun of demo class”;

}

};

int main()

{

demo d;

d.fun().gun().sun().mun();

return 0;

}

Output:-

fun of demo class

gun of demo class

sun of demo class

mun of demo class

  • If we want to achieve function chaining, we have to write each and every function except last function returning an object.
  • This return value of a function is used for calling next function from the chain.
  • In function chaining, there is no restriction of no of functions in a chain.
  • In a functions are called in L->R order.
  • In above example, we return *this and ‘this’ is a pointer which points to a caller object and we are returning a caller object after execution.
  • Means using this technique we can call a function by using an object
  • And we can modify a content of that object inside a function and return that modified object.

For more reading about technology news in singapore and seo to online marketing do view more about other pages.

Sourabh Bhunje

Sourabh Bhunje, B.E. IT from Pune University. Currently Working at Techliebe. Professional Skills: Programming - Software & Mobile, Web & Graphic Design, Localization, Content Writing, Sub-Titling etc. http://techliebe.com/about-us

Leave a Reply