Open In App

Dynamic _Cast in C++

Last Updated : 07 Jul, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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

Type Casting:

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




// C++ program to demonstrate the use
// of typecasting
#include <iostream>
using namespace std;
 
// Driver Code
int main()
{
    // Variable declaration
    int a, b;
    float c;
 
    a = 20;
    b = 40;
 
    // Typecasting
    c = (float)a * b;
 
    cout << "Result: " << c;
 
    return 0;
}


Output:

Result: 800

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




// C++ program to read the values of two
// variables and stored the result in
// third one
#include <iostream>
using namespace std;
 
int main()
{
    // Variable declaration and
    // initialization
    int a = 7, b = 2;
    float c;
    c = a / b;
 
    cout << "Result:" << c;
 
    return 0;
}


Output:

Result:3

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




// C++ program to read two variable value
// (a, b) and perform typecasting
#include <iostream>
using namespace std;
 
// Driver Code
int main()
{
    // Variable declaration and
    // initialization
    int a = 7, b = 2;
    float c;
 
    // Type Casting
    c = (float)a / b;
    cout << "Result :" << c;
 
    return 0;
}


Output:

Result :3.5

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




// C++ program demonstrate if there
// is no virtual function used in
// the Base class
#include <iostream>
using namespace std;
 
// Base class declaration
class Base {
    void print()
    {
        cout << "Base" << endl;
    }
};
 
// Derived Class 1 declaration
class Derived1 : public Base {
    void print()
    {
        cout << "Derived1" << endl;
    }
};
 
// Derived class 2 declaration
class Derived2 : public Base {
    void print()
    {
        cout << "Derived2" << endl;
    }
};
 
// Driver Code
int main()
{
    Derived1 d1;
 
    // Base class pointer hold Derived1
    // class object
    Base* bp = dynamic_cast<Base*>(&d1);
 
    // Dynamic casting
    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++




// C++ Program demonstrates successful
// dynamic casting and it returns a
// value of type new_type
#include <iostream>
 
using namespace std;
// Base Class declaration
class Base {
    virtual void print()
    {
        cout << "Base" << endl;
    }
};
 
// Derived1 class declaration
class Derived1 : public Base {
    void print()
    {
        cout << "Derived1" << endl;
    }
};
 
// Derived2 class declaration
class Derived2 : public Base {
    void print()
    {
        cout << "Derived2" << endl;
    }
};
 
// Driver Code
int main()
{
    Derived1 d1;
 
    // Base class pointer holding
    // Derived1 Class object
    Base* bp = dynamic_cast<Base*>(&d1);
 
    // Dynamic_casting
    Derived1* dp2 = dynamic_cast<Derived1*>(bp);
    if (dp2 == nullptr)
        cout << "null" << endl;
    else
        cout << "not null" << endl;
 
    return 0;
}


Output:

not null

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




// C++ Program demonstrate if the cast
// fails and new_type is a pointer type
// it returns a null pointer of that type
#include <iostream>
using namespace std;
 
// Base class declaration
class Base {
    virtual void print()
    {
        cout << "Base" << endl;
    }
};
 
// Derived1 class declaration
class Derived1 : public Base {
    void print()
    {
        cout << "Derived1" << endl;
    }
};
 
// Derived2 class declaration
class Derived2 : public Base {
    void print()
    {
        cout << "Derived2" << endl;
    }
};
 
// Driver Code
int main()
{
    Derived1 d1;
    Base* bp = dynamic_cast<Base*>(&d1);
 
    // Dynamic Casting
    Derived2* dp2 = dynamic_cast<Derived2*>(bp);
    if (dp2 == nullptr)
        cout << "null" << endl;
 
    return 0;
}


Output:

null

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




// C++ Program demonstrate if the cast
// fails and new_type is a reference
// type it throws an exception
#include <exception>
#include <iostream>
using namespace std;
 
// Base class declaration
class Base {
    virtual void print()
    {
        cout << "Base" << endl;
    }
};
 
// Derived1 class
class Derived1 : public Base {
    void print()
    {
        cout << "Derived1" << endl;
    }
};
 
// Derived2 class
class Derived2 : public Base {
    void print()
    {
        cout << "Derived2" << endl;
    }
};
 
// Driver Code
int main()
{
    Derived1 d1;
    Base* bp = dynamic_cast<Base*>(&d1);
 
    // Type casting
    Derived1* dp2 = dynamic_cast<Derived1*>(bp);
    if (dp2 == nullptr)
        cout << "null" << endl;
    else
        cout << "not null" << endl;
 
    // Exception handling block
    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
Previous
Next
Share your thoughts in the comments

Similar Reads