Upcasting and Downcasting in C++
With the help of various examples in the C++ programming language, this section will cover Upcasting and Downcasting. Upcasting and downcasting, on the other hand, are two forms of object typecasting. Consider the Parent and Child classes, which have two types of objects, parent_objct and child_objct, which can be cast into Parent to Child and Child to Parent using C++ programming's Upcasting and Downcasting.
Casting in C++ :
When transforming one type of objects to another, the phrase "casting" is commonly used in programming. It's essentially a "forced conversion", in which you change one type to another manually.
Example :
float x = 7.68;
int y;
y = (int)x;
In the above example, we were able to assign a value to y by casting x into an int, despite the fact that y is an int. The float value of x, 7.68 loses all of its digits that are placed after the decimal point and is transformed to an int.
In C++, we may use pointer references to build a "is a" relationship between the parent and child classes. There are two main kinds of casting that may be done:
- Upcasting
- Downcasting
Upcasting in C++ :
Upcasting is the process of creating the pointer or reference of the derived class from the pointer or reference of the base class. When compared to downcasting, upcasting is a safer option. It enables public inheritance, which allows a reference to be automatically cast from one class to the other without the need for an explicit typecast. Upcasting creates an is-a relationship between base and derived classes by default.
Base *pntr = &derived_objct;
The derived class can inherit all of the base class attributes, including data members and the member function, and use the derived class object to run the function, just like a base object.
When a derived class object is provided by the value as a base class object, upcasting can result in object slicing.
Whenever we send out a message to an object that has a virtual member function, the object will perform the proper thing, even if upcasting is used.
Example :
#include <iostream> // std::cout
using namespace std;
class Base
{
public:
void baseFunc()
{
cout<<"Base Function!"<<endl;
}
};
class Derived: public Base
{
public:
void derivedFunc()
{
cout<<"Derived Function!"<<endl;
}
};
int main()
{
Derived dObjct;
//Upcasting – Here, the implicit upcasting is allowed
Base *bPntr = &dObjct;
bPntr -> baseFunc();
return 0;
}
Output :
Base Function!
Explanation :
In the above example, we explained the concept of upcasting. We used a public base class with a void function called baseFunc(). Then we created a derived class from the public base class having a function called derivedFunc(). Then we used implicit upcasting, using a base pointer bPntr pointing towards the derived object dObjct and resulting in the calling of baseFunc().
Downcasting in C++ :
Downcasting is the opposite of upcasting. Upcasting is the polar opposite of downcasting. It changes the value of a base class pointer to a derived class pointer. Manual downcasting is a requirement. It implies we’ll have to define a type cast explicitly.
The explanation for this limitation is that in most circumstances, the is-a connection is not symmetric. The class member procedures that utilised such data members would not really be applicable to the base class if a derived class added additional data members. It is not as safe to downcast as it is to upcast. A downcast is only safe if the object being referenced at runtime is indeed a derived class object.
Derived *d_pntr = &b_objct;
Example :
#include <iostream> // std::cout
using namespace std;
class Base
{
public:
void baseFunc()
{
cout<<"Base Function!"<<endl;
}
};
class Derived: public Base
{
public:
void derivedFunc()
{
cout<<"Derived Function!"<<endl;
}
};
int main()
{
Base bObjct;
// explicit type casting is required here
Derived *dPntr = (Derived *) &bObjct;
dPntr -> derivedFunc();
return 0;
}
Output :
Derived Fun
Explanation :
In the above example, we explained the concept of downcasting. We used a public base class with a void function called baseFunc(). Then we created a derived class from the public base class having a function called derivedFunc(). Then we used explicit type casting, using a derived pointer dPntr pointing towards the base object bObjct and resulting in the calling of derivedFunc().