Download as pdf or txt
Download as pdf or txt
You are on page 1of 48

Pointers, Virtual Functions &

Polymorphism

In C++
Pointers
Pointer is a derived data type that refers to the address of another
variable. A pointer variable tells that where to get the data
instead of telling the actual data.

Declaring and Initializing Pointers:


The declaration of the pointer is based on the data type of the
variable it points to. E.g.
data-type *pointer-variable;

At any point of time a pointer variable can point to only one data
type. Int *ptr;
Here ptr contains the memory location of any integer variable.
e.g. int *ptr , a; //Declaration
ptr=&a; //Initialization
Pointers
We can also declare a Pointer variable that points to
another variable.
Important:
1. Generic Pointers or Void Pointers: Pointers that can
refer to variables of any data type. Before using
these pointers, we must type cast the variables to the
specific data types that they point to.
2. Null Pointers: The Pointers that are not initialized in
the program.
3. Pointers of any data type can be assigned with one
value i.e. ‘0’ called null address.
Manipulation of Pointers
To access the values and making the changes in the
values of the variables, we use the indirection
operator i.e. “*”, It is also called deference operator.

Caution: Before referencing a pointer we have to assign


a value to it otherwise there will give a run time error
by referring to any other location in memory.
Pointer Expression and Pointer Arithmetic
Normally following arithmetic operations are performed.
❖ A pointer can be incremented(++) or decremented(--).
❖ Any Integer can be added to or decremented from a pointer.
❖ One Pointer can be subtracted from other.
• e.g. Int a[6];
• int *aptr;
• aptr=&a[0];
• Here aptr refers to the base address of array a.
• By Incrementing aptr (i.e. aptr++)we can move to the next location in
array.
• Similarly by decrementing aptr (i.e. aptr--)we can move to the previous
location in array.
• Imp: Here Pointer arithmetic is applicable as the elements are at the
neighbouring locations.
Pointers with Arrays & Strings
Pointers are associated with arrays as:
❖ Pointers are useful to allocate arrays dynamically
❖ Efficient tools to access the elements of an array.
❖ We can decide the array size at run time.
For this we use malloc() and calloc().
We can declare pointers to arrays as ;
int *ptr;
ptr = number[0]; OR ptr = number;
Array of Pointers
An array of Pointer is an array of addresses i.e
all the elements of the Pointer array points to an
item of the data array. An array of Pointer is
declared as
int *abc[10];
It is an array of ten pointers ie. Addresses all of
them points to an integer. Before initializing they
point to some unknown values in the memory
space.
Pointers & Strings
A String is a one dimensional array of characters, that
starts with index 0 and ends with a null character ‘\0’
in C++. A pointer variable can access a string by
referring to its first character. We can assign the values
to the arrays in two ways:
char num[]=“one”; Here an array of four characters
is declared ‘o’, ‘n’, ‘e’ and ‘\0’
const char *numptr=“one”; here a pointer variable is
generated which points to the first character ‘o’ of
string.
Pointers to Functions
Pointers to Functions are used for dynamic binding, and event based
applications.
The Pointer to function is also known as callback function. Pointers to
functions are used for
❖ Referring to a function
❖ Function can be selected dynamically at run time.
❖ Function can be passed as an argument to another function.
❖ There are two types of Function Pointers
• (i) Points to Static Members Functions.
• (ii) Points to non static member functions. (It requires
hidden argument)
• Pointer to Function is Declared as:
• data_type(*function_name)();
Pointers to objects
A Pointer can also point to the object created by a class. E.g.
Class item
{
int code;
float price;
public:
void getdata(int a , float b)
{
code=a;
price=b;
}
void show()
{
cout<<“Code : ”<< code<<“\n”;
cout<<“Price : ”<< price<<“\n”;
}
};
Item x;
Item *ptr=&x;
Now the member functions can be pointed in two ways.
x.getdata(100,75.5);
x.show();
OR
ptr->getdata(100, 75.5);
ptr->show(); OR (*ptr).show();
Pointers to objects
The same declaration can also be done as:
item *ptr=new item;
Here new operator allocates sufficient memory to ptr.
Imp: If a class has a constructor with parameters and does not
include any empty constructor. Then we must pass the
parameters when we create any object.
Similarly we can create an array of objects using Pointers e.g.
item *ptr=new item[10];
Here in such cases if a class has a constructor then it must have
an empty constructor.
this Pointer
• this represents an object that invokes a member function. this
is a pointer that points to the object for which this function was
called.

e.g the statement A.max() will set the pointer this to the address
of the object A.

• When a member function is called, it is automatically passed


an implicit argument that is a pointer to the invoking object.
this Pointer
e.g. Class ABC
{
int a;
::::::::::::::
};
here a can be initialized in a member function like: a=345;
• Same can be done like: this->a = 345;
• this pointer is implicitly called when overloading the
operators using member function.
• Recall when we overload a binary operator using member
function, we pass one argument other is implicitly passed
using the pointer this.
• Another important application is that pointer this returns the
object it points to.
return *this;
this Pointer
e.g.
person & greater (person &x)
{
if x.age>age
return x;
else
return *this;
}

Suppose we have a call max=A. greater(B);

• The function will return the object B (argument object) if the age of the
person B is greater than that of A, otherwise, it will return the object A
(invoking object) using the pointer this.
#include <iostream> int main()
using namespace std; {
class pwr { pwr x(4.0, 2), y(2.5, 1), z(5.7, 0);
cout << x.get_pwr() << " ";
double b;
cout << y.get_pwr() << " ";
int e; cout << z.get_pwr() << "\n";
double val; return 0;
public: }
pwr(double base, int exp);
double get_pwr() { return val; }
};
//Version of pwr using this pointer
pwr::pwr(double base, int exp)
pwr::pwr(double base, int exp)
{ {
b = base; this->b = base;
e = exp; this->e = exp;
val = 1; this->val = 1;
if(exp==0) return; if(exp==0) return;
for( ; exp>0; exp--)
for( ; exp>0; exp--) val = val * b;
this->val = this->val * this->b;
} }
Memory Management Operators
• C++ supports two unary operators to perform DMA, As these operators
manage memory on free store they are called free store operators .
• An object created by new can be destroyed by delete operator. Such as:

pointer_variable=new data_type

• Here new allocates the sufficient memory to the object of type data_type,
and assigns the address of that location in pointer_variable.

e.g. p=new int; // here p is a pointer of type int


q= new float; // here q is a pointer of type float
• Here p & q must have already been declared with the appropriate data
types. This can be combined also e.g.
Int *p=new int;
float *q=new float;
• Then the data is stored as; p=25;
q=7.6;
• All this can be done in one statement also:
int *p = new int(25);
float *q = new float(7.6);
Memory Management Operators
• Same can be done for user defined data types such as arrays, classes etc.
pointer-variable = new data-type[size];

e.g int *p = new int [10];

• Similarly when data is no longer required, we use delete operator.


delete pointer-variable;
e.g delete p;

• To delete an array allocated memory dynamically


delete [size] pointer-variable;

e.g. delete [ ]p; will delete the entire array.

• If sufficient memory is not available then the new will return a null pointer.
• So it is better to check dynamically that memory has been allocated or not.
p=new int;
if(!p)
{ cout<<“Allocation Failed \n”; }
#include <iostream> #include <iostream>
#include <new> #include <new>
using namespace std; using namespace std;
int main()
int main()
{
{ int *p, i;
int *p; try {
try { p = new int [10]; // allocate 10 integer array
p = new int (87); // initialize to 87 } catch (bad_alloc xa) {
} catch (bad_alloc xa) { cout << "Allocation Failure\n";
return 1;
cout << "Allocation Failure\n";
}
return 1;
} for(i=0; i<10; i++ )
cout << "At " << p << " "; p[i] = i;
cout << "is the value " << *p << "\n"; for(i=0; i<10; i++)
delete p; cout << p[i] << " ";
delete [] p; // release the array
return 0;
return
}
Advantages of new over malloc()
1. It automatically computes the size of the data object. We need not use the
operator sizeof.

2. It automatically returns the correct Pointer type, So we do not need to use


typecast.

3. It is possible to initialize the object while creating the memory space.

4. Like any other operator, new and delete can be overloaded.


Allocating Objects
#include <iostream>
#include <new>
int main()
#include <cstring>
{
using namespace std;
balance *p;
class balance {
char s[80];
double cur_bal;
double n;
char name[80];
// this version uses an initializer
public:
try {
balance(double n, char *s) {
p = new balance (12387.87, "Ralph Wilson");
cur_bal = n;
} catch (bad_alloc xa) {
strcpy(name, s);
cout << "Allocation Failure\n";
}
return 1;
~balance() {
}
cout << "Destructing ";
p->get_bal(n, s);
cout << name << "\n";
cout << s << "'s balance is: " << n;
}
cout << "\n";
void get_bal(double &n, char *s) {
delete p;
n = cur_bal;
return 0;
strcpy(s, name);
}
}
};
Overloading New and Delete Operators
#include <iostream>
#include <cstdlib>
#include <new>
using namespace std;
class loc {
int longitude, latitude;
public:
loc() {}
loc(int lg, int lt) {
longitude = lg;
latitude = lt;
}
void show() {
cout << longitude << " ";
cout << latitude << "\n";
}
void *operator new(size_t size);
void operator delete(void *p);
};
// new overloaded relative to loc.
void *loc::operator new(size_t size)
{
void *p;
cout << "In overloaded new.\n";
p = malloc(size);
if(!p) {
bad_alloc ba; throw ba;
}
return p;
}
// delete overloaded relative to loc.
void loc::operator delete(void *p)
{
cout << "In overloaded delete.\n";
free(p);
}
int main()
{
loc *p1, *p2;
try {
p1 = new loc (10, 20);
} catch (bad_alloc xa) {
cout << "Allocation error for p1.\n";
return 1;
}
try {
p2 = new loc (-10, -20);
} catch (bad_alloc xa) {
cout << "Allocation error for p2.\n";
return 1;
}
p1->show();
p2->show();
delete p1;
delete p2;
int * p= new int(40); delete p;
Pointers to Derived Classes
We can declare the pointers to the base class as well as the
pointers to the derived classes. Pointers to the base classes are
type-compatible to the objects of the derived classes. Hence a
single pointer can be made to point to the different classes. E.g.
Here B is a base class, D is Derived class.
B *cptr;
B b;
D d;
cptr=&b;
we can also make the cptr to point to object d also.
cptr=&d;
As d is an object derived from the class B.
Pointers to Derived Class

Problem: here is that pointer to the object of the derived class will
point only to those members of D that have been inherited
from the base class. It cannot access the original members of
the class D. If we have a member function with the same
name in the base class and in the derived class then cptr will
always access the base class member.

Hence to access the individual members of the derived class we


can use another pointer to point to those members.
#include <iostream> int main()
using namespace std; {
class base { base *bp;
derived d;
int i;
derived *d1;
public: bp = &d; // base pointer points to derived
void set_i(int num) { i=num; } object
int get_i() { return i; } d1=&d;
}; // access derived object using base pointer
bp->set_i(10);
cout << bp->get_i() << " ";
class derived: public base {
int j; /* The following won't work. You can't access
public: element of a derived class using a base class
void set_j(int num) { pointer.
j=num; bp->set_j(88); // error
} cout << bp->get_j(); // error
*/
int get_j() {
d1=&d;
return j; d1->set_j(88); // error
} cout << d1->get_j(); // error
};
return 0;
}
Virtual Base Class

In C++
Introduction
We may have a case where all the kinds of Inheritance namely multilevel,
multiple, hierarchical are involved.
Grand Parent

Parent 1 Parent 2

Child
Here the Grandparent is sometime referred to a Indirect base Class. Here the
problem arises that the members of the Grandparent class are inherited
twice, through Parent1 and Parent2, hence it gets the duplicate copies.
This duplication can be avoided by making the common Base class as Virtual
base class, while declaring the direct or Intermediate base classes.
Introduction
As Shown:
Class A // Grandparent
{ :::::::
};
Class B1 : Virtual Public A // Parent1
{ ::::::::::
};
Class B2: public Virtual A // Parent2
{ :::::::::
};
Class c: public B1, public B2 //Child
{ :::::::::::: // Here only one copy of A will be
}; // Inherited

Here Virtual and Public can be used in either order. Program Example:
Abstract Class
An Abstract Class is the one, that is not used to create objects. It is used
only to act as Base Class. It is just a design concept in programming, It acts
as a base on which the other classes may be built.
Constructors in Derived Classes
When both the base class and the derived class have the constructors, then the
base constructor is executed first, then the Derived Constructor.

As long as the base class Constructor doesn’t takes any arguments, the derived
class need not have a constructor function. We know that in Inheritance the
object generally is created of the derived class, then it Is the responsibility
of the derived class to pass the arguments to the base class.
In case of Multiple Inheritance: The base classes are constructed in the order
in which they appear in the declaration of the derived class. Similarly

In case of Multilevel Inheritance: The constructors will be executed in the


order of inheritance.

When we create an object of the derived class only then by which mechanism
the arguments are distributed to the various base classes?
Constructors in Derived Classes
The constructor of the derived class receives the entire arguments and then distributes
all of them in the order in which they have been declared in the derived class.
The Base class Constructors are called and executed first then only the derived class
constructors are called and executed.
Derived-Constructer ( ArgList1, Arglist2, … ArglistN, Arglist(D)) :

base(arglist1),
base(arglist2),
:::::::::::::::::
base N(arglistN), arguments for base(N)
{ Body of derived Constructor
}

The header line of the derived-constructor function contains two parts separated by
colon , The first part provides the declaration of the arguments that are passed to the
derived-constructor and the second part lists the function calls to the base
constructors.
base(arglist1), base(arglist2) .. Are the function calls to the base constructors base1(),
base2(). ArglistD provides the parameters that are necessary to initialize the
members of the derived class.
Constructors in Derived Classes
For Example:
D(int a1, int a2, float b1, float b2, int d1):
A(a1, a2),
B(b1,b2)
{
d=d1;
}

Here A(a1, a2) invokes the constructor of Class A and B(b1, b2) invokes the
constructor of Class B. The D() has one argument for itself.
D objD(5, 12, 2.5, 7.54, 30) ;
5 goes to a1, 12 goes to a2, 2.5 goes to b1, 7.54 goes to b2, and 30goes to d1.
The Constructors for virtual base class are invoked before any non-virtual base classes.
If there are multiple virtual base classes, they are invoked in the order in which they
are declared. Any Non-virtual bases are then constructed before the derived class
constructor is executed.
Example;
Constructors in Derived Classes
• Another method to initialize the objects is by using the initialization List in the Constructor
Function.
constructor (arglist): initialization-section
{ assignment-section
}
We can use the initialization section to provide initial values to the base constructors and also to
initialize its own class members. E.g.
Class xyz
{
int a; int b;
Public:
xyz( int I, int j) : a(i), b( 2 * j ) { }
};
Main()
{
xyz x(2 3,);
}
Here a is 2, b is 6.
If we have xyz(int I, int j) : b( I ) , a ( I + j ) { } Then the values are a=5, b=2

Example:
Virtual Functions
• Virtual function is a member function that is declared within a base class and
redefined by a derived class
• When a class containing a virtual function is inherited, the derived class redefines
the virtual function to fit its own needs.
• Virtual functions implement the "one interface, multiple methods" philosophy that
underlies polymorphism.
• When a base pointer points to a derived object that contains a virtual function, C++
determines which version of that function to call based upon the type of object
pointed to by the pointer
• This determination is made at runtime. Thus, when different objects are pointed to,
different versions of the virtual function are executed.
#include <iostream> int main()
using namespace std; {
class base { base *p, b;
public: derived1 d1;
derived2 d2; // point to base
virtual void vfunc() {
p = &b;
cout << "This is base's vfunc().\n"; p->vfunc(); // access base's vfunc()
}
}; // point to derived1
class derived1 : public base { p = &d1;
public: p->vfunc();
// access derived1's vfunc()
void vfunc() {
cout << "This is derived1's vfunc().\n"; // point to derived2
} p = &d2;
}; p->vfunc(); //access derived2's vfunc()
class derived2 : public base { return 0;
public: }
void vfunc() {
cout << "This is derived2's vfunc().\n";
}
};
#include <iostream>
using namespace std; int main()
{
class base { base* bptr;
public: derived d;
virtual void print() bptr = &d;
{
cout << "print base class" << endl; // virtual function, binded at runtime
} bptr->print();
//Here, Derived version of print will be called
void show()
{
cout << "show base class" << endl; // Non-virtual function, binded at compile time
} bptr->show();
}; //Base version of show will be called
}
class derived : public base {
public:
void print()
{
cout << "print derived class" << endl;
}

void show()
{
cout << "show derived class" << endl;
}
};
Virtual Functions
Note:
•We must access virtual functions through the use of a pointer declared as a
pointer to a base class.
•Although you can call a virtual function in the "normal" manner by using an
object's name and the dot operator, it is only when access is through a
base-class pointer (or reference) that run-time polymorphism is achieved.

E.g; d2.vfunc(); // calls derived2's vfunc() is valid


Basic Rules for Virtual Functions
• Virtual functions must be a member of some class.
• They cant be static members
• They are accessed by object pointers
• A virtual function can be a friend of another class.
• A virtual function in a base class must be defined even though it may not be
used .
• The most important is that the prototype for a redefined virtual function
must match exactly the prototype specified in the base class.
• We cannot have virtual constructors but we can have virtual destructors.
• A base ptr can point to a derived class object, the reverse is not true.
• If a virtual function is defined in the base class, it need not be necessarily
defined in the derived class.
Calling a virtual function through a base class
reference
• A base-class reference can be used to refer to an object of the base class or any
object derived from that base
• When a virtual function is called through a base-class reference, the version of the
function executed is determined by the object being referred to at the time of the
call.
class derived2 : public base {
public:
/* Here, a base class reference is used to access void vfunc() {
a virtual function. */ cout << "This is derived2's vfunc().\n";
#include <iostream> }
using namespace std; };
class base { // Use a base class reference parameter.
public: void f(base &r) {
virtual void vfunc() { r.vfunc();
cout << "This is base's vfunc().\n"; }
} int main()
}; {
class derived1 : public base { base b;
public: derived1 d1;
void vfunc() { derived2 d2;
cout << "This is derived1's vfunc().\n"; f(b); // pass a base object to f()
} f(d1); // pass a derived1 object to f()
}; f(d2); // pass a derived2 object to f()
return 0;
}
Virtual functions are inherited
#include <iostream>
int main()
using namespace std;
{
class base { base *p, b;
public: derived1 d1;
virtual void vfunc() { derived2 d2;
cout << "This is base's vfunc().\n"; // point to base
} p = &b;
p->vfunc(); // access base's vfunc()
};
// point to derived1
class derived1 : public base { p = &d1;
public: p->vfunc(); // access derived1's vfunc()
void vfunc() { // point to derived2
cout << "This is derived1's vfunc().\n"; p = &d2;
} p->vfunc(); // access derived2's vfunc()
return 0;
};
}
/* derived2 inherits virtual function vfunc() from
derived1. */
class derived2 : public derived1 {
public:
// vfunc() is still virtual
void vfunc() {
cout << "This is derived2's vfunc().\n";
}
Virtual functions are hierarchical
#include <iostream>
using namespace std; int main()
class base { {
base *p, b;
public:
derived1 d1;
virtual void vfunc() { derived2 d2;
cout << "This is base's vfunc().\n"; // point to base
} p = &b;
}; p->vfunc(); // access base's vfunc()
class derived1 : public base { // point to derived1
p = &d1;
public:
p->vfunc(); // access derived1's vfunc()
void vfunc() { // point to derived2
cout << "This is derived1's vfunc().\n"; p = &d2;
} p->vfunc(); // use base's vfunc()
}; return 0;
class derived2 : public base { }
public:
// vfunc() not overridden by derived2, base's is used
};
Pure Virtual Functions
• When a virtual function is not redefined by a derived class, the version defined in
the base class will be used.
• In many situations there can be no meaningful definition of a virtual function within
a base class. It only serves as a placeholder
• A base class may not be able to define an object sufficiently to allow a base-class
virtual function to be created. Further, in some situations you will want to ensure
that all derived classes override a virtual function.
• To handle these two cases, C++ supports the pure virtual function
• A pure virtual function is a virtual function that has no definition within the base
class. To declare a pure virtual function, use this general form:

virtual type func-name(parameter-list) = 0;


• When a virtual function is made pure, any derived class must provide its own
definition. If the derived class fails to override the pure virtual function, a compile-
time error will result.
#include <iostream>
using namespace std; class octtype : public number {
class number { public:
protected: void show() {
int val; cout << oct << val << "\n";
public: }
void setval(int i) { val = i; } };
// show() is a pure virtual function int main()
virtual void show() = 0;
{
};
dectype d;
hextype h;
class hextype : public number {
octtype o;
public:
d.setval(20);
void show() {
d.show(); // displays 20 - decimal
cout << hex << val << "\n";
h.setval(20);
}
h.show(); // displays 14 - hexadecimal
}; o.setval(20);
class dectype : public number { o.show(); // displays 24 - octal
public: return 0;
void show() { }
cout << val << "\n";
}
};
Abstract Classes
• A class that contains at least one pure virtual function is said to be abstract.
• Because an abstract class contains one or more functions for which there is no
definition (that is, a pure virtual function), no objects of an abstract class may be
created.
• Although you cannot create objects of an abstract class, you can create pointers and
references to an abstract class.
• This allows abstract classes to support run-time polymorphism, which relies upon
base-class pointers and references to select the proper virtual function
• If we do not override the pure virtual function in derived class, then derived class
also becomes abstract class.
• An abstract class can have constructors.
#include<iostream> class Derived: public Base
using namespace std; {
int y;
public:
// An abstract class with constructor
Derived(int i, int j):Base(i) { y = j; }
class Base void fun() { cout << "x = " << x << ", y = " <<
{ y<<'\n'; }
protected: };
int x;
public: int main(void)
{
virtual void fun() = 0;
Derived d(4, 5);
Base(int i) { d.fun();
x = i;
cout<<"Constructor of base called\n"; //object creation using pointer of base class
} Base *ptr=new Derived(6,7);
}; ptr->fun();
return 0;
}
Early Binding Vs Late Binding
Early binding refers to events that occur at compile time. In essence, early binding
occurs when all information needed to call a function is known at compile time. (Put
differently, early binding means that an object and a function call are bound during
compilation.) Examples of early binding include normal function calls (including
standard library functions), overloaded function calls, and overloaded operators. The
main advantage to early binding is efficiency. Because all information necessary to call
a function is determined at compile time, these types of function calls are very fast.

The opposite of early binding is late binding. As it relates to C++, late binding refers to
function calls that are not resolved until run time. Virtual functions are used to achieve
late binding. As you know, when access is via a base pointer or reference, the virtual
function actually called is determined by the type of object pointed to by the pointer.
Because in most cases this cannot be determined at compile time, the object and the
function are not linked until run time. The main advantage to late binding is flexibility.
Unlike early binding, late binding allows you to create programs that can respond to
events occurring while the program executes without having to create a large amount
of "contingency code." Keep in mind that because a function call is not resolved until
run time, late binding can make for somewhat slower execution times.
Virtual Destructor
• A virtual destructor is used to free up the memory space allocated by the derived
class object or instance while deleting instances of the derived class using a base
class pointer object.
• A base or parent class destructor use the virtual keyword that ensures both base
class and the derived class destructor will be called at run time, but it calls the
derived class first and then base class to release the space occupied by both
destructors.
• When an object in the class goes out of scope or the execution of the main()
function is about to end, a destructor is automatically called into the program to free
up the space occupied by the class' destructor function. When a pointer object of the
base class is deleted that points to the derived class, only the parent class destructor
is called due to the early bind by the compiler. In this way, it skips calling the
derived class' destructor, which leads to memory leaks issue in the program. And
when we use virtual keyword preceded by the destructor tilde (~) sign inside the
base class, it guarantees that first the derived class' destructor is called. Then the
base class' destructor is called to release the space occupied by both destructors in
the inheritance class.
#include<iostream> class Derived: public Base
{
using namespace std;
public:
class Base Derived() // Constructor function
{ {
public: cout << "\n Constructor Derived class" ;
Base() // Constructor function. }
{ ~Derived() // Destructor function
{
cout<< "\n Constructor Base class";
cout << "\n Destructor Derived class" ; /* Destructor
} function is not called to release its space. */
~Base() // Destructor function }
{ };
cout<< "\n Destructor Base class"; int main()
} {
Base *bptr = new Derived; // Create a base class pointer
};
object
delete bptr; /* Here pointer object is called to delete the
space occupied by the destructor.*/
}
Output:
Constructing base
Constructing derived
Destructing base
#include<iostream> class Derived: public Base
using namespace std; {
class Base public:
Derived() // Constructor function.
{
{
public: cout << "\n Constructor Derived class" ; /* After
Base() // Constructor member function. print the Constructor Base, now it will prints. */
{ }
cout << "\n Constructor Base class"; ~Derived() // Destructor function
} {
cout << "\n Destructor Derived class"; /* The
virtual ~Base() // Define the virtual destructor
virtual Base Class Destructor calls it before calling
function to call the Destructor Derived function.
the Base Class Destructor. */
{ }
cout << "\n Destructor Base class"; / };
}
}; int main()
{
Base *bptr = new Derived; // A pointer object
reference the Base class.
Output: delete bptr; // Delete the pointer object.
Constructing base }
Constructing derived
Destructing derived
Destructing base

You might also like