Dynamic _Cast in C++
Last Updated :
07 Jul, 2023
C++ is a powerful language. In C++ we can write a structured program and object-oriented program also. In this article, we will focus on dynamic_cast in C++. Now before start dynamic_cast in C++, first understand what is type casting in C++.’
Casting is a technique by which one data type to another data type. The operator used for this purpose is known as the cast operator. It is a unary operator which forces one data type to be converted into another data type. It takes on the format:
Syntax:
(Cast type) expression;
or
Cast type (expression)
Program 1:
C++
#include <iostream>
using namespace std;
int main()
{
int a, b;
float c;
a = 20;
b = 40;
c = ( float )a * b;
cout << "Result: " << c;
return 0;
}
|
Explanation: In the above example first, the variable a is converted to float then multiplied by b, now the result is also floating float then the result is assigned to the variable c. Now, the value of c is 800.
Program 2:
C++
#include <iostream>
using namespace std;
int main()
{
int a = 7, b = 2;
float c;
c = a / b;
cout << "Result:" << c;
return 0;
}
|
Explanation: In the above case, the variable c is 3, not 3.5, because variables a and b both are integer types therefore a/b is also an integer type. After calculating a/b that is int type is assigned to the variable c which is float type. But a/b is int type i.e., 7/2 is 3, not 3.5. Therefore, the value of variable c is 3.
Program 3:
C++
#include <iostream>
using namespace std;
int main()
{
int a = 7, b = 2;
float c;
c = ( float )a / b;
cout << "Result :" << c;
return 0;
}
|
Explanation: Now, the variable c is 3.5, because in the above expression first a is converted into float therefore a/b is also float type. 7.0/2 is 3.5. Then that is assigned to the variable c.
C++ supports four types of casting:
1.Static Cast
2. Dynamic Cast
3. Const Cast
4. Reinterpret Cast
Static Cast: This is the simplest type of cast that can be used. It is a compile-time cast. It does things like implicit conversions between types (such as int to float, or pointer to void*), and it can also call explicit conversion functions (or implicit ones).
Dynamic Cast: A cast is an operator that converts data from one type to another type. In C++, dynamic casting is mainly used for safe downcasting at run time. To work on dynamic_cast there must be one virtual function in the base class. A dynamic_cast works only polymorphic base class because it uses this information to decide safe downcasting.
Syntax:
dynamic_cast <new_type>(Expression)
- Downcasting: Casting a base class pointer (or reference) to a derived class pointer (or reference) is known as downcasting. In figure 1 casting from the Base class pointer/reference to the “derived class 1” pointer/reference showing downcasting (Base ->Derived class).
- Upcasting: Casting a derived class pointer (or reference) to a base class pointer (or reference) is known as upcasting. In figure 1 Casting from Derived class 2 pointer/reference to the “Base class” pointer/reference showing Upcasting (Derived class 2 -> Base Class).
As we mention above for dynamic casting there must be one Virtual function. Suppose If we do not use the virtual function, then what is the result?
In that case, it generates an error message “Source type is not polymorphic”.
C++
#include <iostream>
using namespace std;
class Base {
void print()
{
cout << "Base" << endl;
}
};
class Derived1 : public Base {
void print()
{
cout << "Derived1" << endl;
}
};
class Derived2 : public Base {
void print()
{
cout << "Derived2" << endl;
}
};
int main()
{
Derived1 d1;
Base* bp = dynamic_cast <Base*>(&d1);
Derived2* dp2 = dynamic_cast <Derived2*>(bp);
if (dp2 == nullptr)
cout << "null" << endl;
return 0;
}
|
Output
./Solution.cpp: In function 'int main()':
./Solution.cpp:42:47: error: cannot dynamic_cast 'bp' (of type 'class Base*') to type 'class Derived2*' (source type is not polymorphic)
Derived2* dp2 = dynamic_cast<Derived2*>(bp);
Virtual functions include run-time type information and there is no virtual function in the base class. So this code generates an error.
Case 1: Let’s take an example of dynamic_cast which demonstrates if the casting is successful, it returns a value of type new_type.
C++
#include <iostream>
using namespace std;
class Base {
virtual void print()
{
cout << "Base" << endl;
}
};
class Derived1 : public Base {
void print()
{
cout << "Derived1" << endl;
}
};
class Derived2 : public Base {
void print()
{
cout << "Derived2" << endl;
}
};
int main()
{
Derived1 d1;
Base* bp = dynamic_cast <Base*>(&d1);
Derived1* dp2 = dynamic_cast <Derived1*>(bp);
if (dp2 == nullptr)
cout << "null" << endl;
else
cout << "not null" << endl;
return 0;
}
|
Explanation: In this program, there is one base class and two derived classes (Derived1, Derived2), here the base class pointer hold derived class 1 object (d1). At the time of dynamic_casting base class, the pointer held the Derived1 object and assigning it to derived class 1, assigned valid dynamic_casting.
Case 2: Now, If the cast fails and new_type is a pointer type, it returns a null pointer of that type.
C++
#include <iostream>
using namespace std;
class Base {
virtual void print()
{
cout << "Base" << endl;
}
};
class Derived1 : public Base {
void print()
{
cout << "Derived1" << endl;
}
};
class Derived2 : public Base {
void print()
{
cout << "Derived2" << endl;
}
};
int main()
{
Derived1 d1;
Base* bp = dynamic_cast <Base*>(&d1);
Derived2* dp2 = dynamic_cast <Derived2*>(bp);
if (dp2 == nullptr)
cout << "null" << endl;
return 0;
}
|
Explanation: In this program, at the time of dynamic_casting base class pointer holding the Derived1 object and assigning it to derived class 2, which is not valid dynamic_casting. So, it returns a null pointer of that type in the result.
Case 3:Now take one more case of dynamic_cast, If the cast fails and new_type is a reference type, it throws an exception that matches a handler of type std::bad_cast and gives a warning: dynamic_cast of “Derived d1” to “class Derived2&” can never succeed.
C++
#include <exception>
#include <iostream>
using namespace std;
class Base {
virtual void print()
{
cout << "Base" << endl;
}
};
class Derived1 : public Base {
void print()
{
cout << "Derived1" << endl;
}
};
class Derived2 : public Base {
void print()
{
cout << "Derived2" << endl;
}
};
int main()
{
Derived1 d1;
Base* bp = dynamic_cast <Base*>(&d1);
Derived1* dp2 = dynamic_cast <Derived1*>(bp);
if (dp2 == nullptr)
cout << "null" << endl;
else
cout << "not null" << endl;
try {
Derived2& r1 = dynamic_cast <Derived2&>(d1);
}
catch (std::exception& e) {
cout << e.what() << endl;
}
return 0;
}
|
Output:
warning: dynamic_cast of ‘Derived1 d1’ to ‘class Derived2&’ can never succeed Derived2& r1 = dynamic_cast<Derived2&>(d1);
Note:
- A Dynamic_cast has runtime overhead because it checks object types at run time using “Run-Time Type Information“.
- If there is a surety we will never cast to wrong object then always avoid dynamic_cast and use static_cast.
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...