dynamic_cast
dynamic_cast
is one of the four casting operators in C++. It's primarily used for safe downcasting in inheritance hierarchies. Unlike static_cast
, dynamic_cast
performs runtime type checking, making it particularly useful in scenarios involving polymorphism.
nullptr
for pointers or throws std::bad_cast
for references if the cast fails#include <iostream>
class Base {
public:
virtual void print() { std::cout << "Base" << std::endl; }
virtual ~Base() {}
};
class Derived : public Base {
public:
void print() override { std::cout << "Derived" << std::endl; }
void derivedMethod() { std::cout << "Derived method" << std::endl; }
};
int main() {
Base* basePtr = new Derived();
// Safe downcasting
Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);
if (derivedPtr) {
derivedPtr->derivedMethod();
} else {
std::cout << "Cast failed" << std::endl;
}
delete basePtr;
return 0;
}
dynamic_cast
is used to safely downcast from Base*
to Derived*
.basePtr
actually points to a Derived
object.dynamic_cast
returns nullptr
, allowing for safe checking.dynamic_cast
: safe downcasting in polymorphic class hierarchies.#include <iostream>
class Animal {
public:
virtual void speak() = 0;
virtual ~Animal() {}
};
class Flyable {
public:
virtual void fly() = 0;
virtual ~Flyable() {}
};
class Bird : public Animal, public Flyable {
public:
void speak() override { std::cout << "Chirp" << std::endl; }
void fly() override { std::cout << "Bird is flying" << std::endl; }
};
int main() {
Bird* bird = new Bird();
Animal* animal = bird;
// Cross-casting from Animal* to Flyable*
Flyable* flyable = dynamic_cast<Flyable*>(animal);
if (flyable) {
flyable->fly();
} else {
std::cout << "Cast failed" << std::endl;
}
delete bird;
return 0;
}
Animal*
to Flyable*
, which are not directly related but share a common derived class.dynamic_cast
successfully performs this cast because the actual object is a Bird
, which inherits from both Animal
and Flyable
.dynamic_cast
's ability to navigate complex inheritance hierarchies.dynamic_cast
with References#include <iostream>
#include <stdexcept>
class Base {
public:
virtual ~Base() {}
};
class Derived : public Base {
public:
void derivedFunction() { std::cout << "Derived function" << std::endl; }
};
void processDerived(Base& base) {
try {
Derived& derived = dynamic_cast<Derived&>(base);
derived.derivedFunction();
} catch (const std::bad_cast& e) {
std::cout << "Cast failed: " << e.what() << std::endl;
}
}
int main() {
Base baseObj;
Derived derivedObj;
processDerived(derivedObj); // Succeeds
processDerived(baseObj); // Throws and catches std::bad_cast
return 0;
}
dynamic_cast
used with references instead of pointers.dynamic_cast
throws std::bad_cast
on failure instead of returning nullptr
.processDerived
function attempts to cast its Base&
parameter to Derived&
.derivedObj
but fails for baseObj
, demonstrating exception handling with dynamic_cast
.#include <iostream>
#include <vector>
#include <memory>
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() {}
};
class Circle : public Shape {
public:
void draw() override { std::cout << "Drawing Circle" << std::endl; }
};
class Square : public Shape {
public:
void draw() override { std::cout << "Drawing Square" << std::endl; }
};
int main() {
std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Circle>());
shapes.push_back(std::make_unique<Square>());
shapes.push_back(std::make_unique<Circle>());
for (const auto& shape : shapes) {
shape->draw();
if (dynamic_cast<Circle*>(shape.get())) {
std::cout << "This is a Circle" << std::endl;
} else if (dynamic_cast<Square*>(shape.get())) {
std::cout << "This is a Square" << std::endl;
}
}
return 0;
}
dynamic_cast
for Runtime Type Identification (RTTI).Shape
pointers, containing both Circle
and Square
objects.dynamic_cast
is used to determine the actual type of each object at runtime.dynamic_cast
can be used to implement type-specific behavior in polymorphic scenarios.Performance: dynamic_cast
has a runtime cost due to type checking. Use it judiciously in performance-critical code.
Design Implications: Frequent use of dynamic_cast
might indicate a design that could benefit from refactoring.
Compiler Support: Ensure that Runtime Type Information (RTTI) is enabled in your compiler settings.
Smart Pointers: dynamic_cast
works well with smart pointers, enhancing both safety and convenience.
dynamic_cast
is a powerful tool in C++ for safe downcasting and runtime type checking in polymorphic class hierarchies. It's particularly useful when dealing with inheritance and when the exact type of an object needs to be determined at runtime. Unlike static_cast
, dynamic_cast
performs runtime checks, making it safer but also incurring a performance cost. It's commonly used for downcasting, cross-casting, and as part of Runtime Type Identification (RTTI) techniques. While dynamic_cast
provides important safety features, its frequent use might indicate areas where the design could be improved. When used appropriately, dynamic_cast
enhances type safety and enables more flexible handling of polymorphic types in C++ programs.