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.
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.