← Back to C++ Course | Chapter 17: Advanced C++ | Lesson 9 of 17

C++ dynamic_cast

dynamic_cast safely changes a parent pointer into a child pointer while the program runs, and tells you if it is not really that child. It is like checking a label before opening the box.
Syntax
cpp
Derived *pointer_name = dynamic_cast<Derived*>(base_pointer);  // nullptr if it fails

Derived &reference_name = dynamic_cast<Derived&>(base_reference);  // throws if it fails

What is dynamic_cast?

The dynamic_cast operator is used for safe downcasting in polymorphic class hierarchies. It checks at runtime whether a base class pointer actually points to a specific derived class object.

Example: What is dynamic_cast?

cpp
// Include std::cout and std::cin
#include <iostream>

// Define the type Animal
class Animal {
// Members below can be accessed from outside the class
public:
	virtual ~Animal() {}
};

// Define the type Dog
class Dog : public Animal {};

// Program execution starts in main()
int main() {
	// Allocate an object on the heap with new
	Animal *a = new Dog();
	Dog *d = dynamic_cast<Dog *>(a);
	// Print to the console with cout
	std::cout << (d != nullptr) << std::endl;
	// Free the heap memory with delete
	delete a;
	return 0;
}

Casting with References

You can also use dynamic_cast with references. Because there is no such thing as a null reference, dynamic_cast throws a 'std::bad_cast' exception if the conversion fails.

Example: Casting with References

cpp
// Include std::cout and std::cin
#include <iostream>

// Define the type Animal
class Animal {
// Members below can be accessed from outside the class
public:
	virtual ~Animal() {}
};

// Define the type Dog
class Dog : public Animal {};

// Program execution starts in main()
int main() {
	Dog realDog;
	Animal &a = realDog;
	// Try code that might throw an exception
	try {
		Dog &d = dynamic_cast<Dog &>(a);
		// Print to the console with cout
		std::cout << "Cast succeeded" << std::endl;
	// Handle the exception if one was thrown
	} catch (std::bad_cast &e) {
		std::cout << "Cast failed" << std::endl;
	}
	return 0;
}

Requirement of Polymorphism

For dynamic_cast to work, the base class must be polymorphic. This means the base class must declare at least one virtual function, such as a virtual destructor.

Example: Requirement of Polymorphism

cpp
// Include std::cout and std::cin
#include <iostream>

// Define the type Animal
class Animal {
// Members below can be accessed from outside the class
public:
	virtual ~Animal() {}
};

// Define the type Dog
class Dog : public Animal {};

// Program execution starts in main()
int main() {
	// Allocate an object on the heap with new
	Animal *a = new Dog();
	Dog *d = dynamic_cast<Dog *>(a);
	// Print to the console with cout
	std::cout << (d != nullptr) << std::endl;
	// Free the heap memory with delete
	delete a;
	return 0;
}

Upcasting vs Downcasting

Upcasting converts a derived pointer to a base pointer and is handled implicitly by the compiler. Downcasting converts a base pointer to a derived pointer and requires an explicit dynamic_cast to perform runtime checks.

Example: Upcasting vs Downcasting

cpp
// Include std::cout and std::cin
#include <iostream>

// Define the type Animal
class Animal {
// Members below can be accessed from outside the class
public:
	virtual ~Animal() {}
};

// Define the type Dog
class Dog : public Animal {};

// Program execution starts in main()
int main() {
	Dog d;
	Animal *a = &d;
	Dog *back = dynamic_cast<Dog *>(a);
	// Print to the console with cout
	std::cout << (back != nullptr) << std::endl;
	// Return 0 to signal that the program finished successfully
	return 0;
}

Downcasting Best Practices

Always check if the returned pointer from a dynamic_cast is nullptr before using it. This prevents your program from crashing if the cast fails at runtime.

Example: Downcasting Best Practices

cpp
// Include std::cout and std::cin
#include <iostream>

// Define the type Animal
class Animal {
// Members below can be accessed from outside the class
public:
	virtual ~Animal() {}
};

// Define the type Dog
class Dog : public Animal {};
class Cat : public Animal {};

// Program execution starts in main()
int main() {
	// Allocate an object on the heap with new
	Animal *a = new Cat();
	Dog *d = dynamic_cast<Dog *>(a);
	// Check whether d == nullptr
	if (d == nullptr) {
		// Print to the console with cout
		std::cout << "Not actually a Dog" << std::endl;
	}
	delete a;
	return 0;
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Using dynamic_cast on a class without virtual functions.
  2. Not checking for nullptr after a failed pointer cast.
  3. Forgetting that a failed reference cast throws std::bad_cast.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.