C++
Beginner
1 min read
Slicing, Upcasting, and Downcasting
Example
#include <iostream>
#include <memory>
#include <vector>
struct Shape {
virtual ~Shape() = default;
virtual std::string type() const { return "Shape"; }
virtual double area() const { return 0.0; }
};
struct Circle : Shape {
explicit Circle(double r) : radius(r) {}
std::string type() const override { return "Circle"; }
double area() const override { return 3.14159 * radius * radius; }
double radius;
};
struct Square : Shape {
explicit Square(double s) : side(s) {}
std::string type() const override { return "Square"; }
double area() const override { return side * side; }
double side;
};
void printSliced(Shape s) { // BAD: slices derived info
std::cout << "sliced type: " << s.type() << "\n";
}
int main() {
Circle c(5.0);
printSliced(c); // prints "Shape", not "Circle"
// Correct: use pointer/reference
std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Circle>(3.0));
shapes.push_back(std::make_unique<Square>(4.0));
for (const auto& s : shapes) {
std::cout << s->type() << " area = " << s->area() << "\n";
// Safe downcast with dynamic_cast
if (auto* circle = dynamic_cast<Circle*>(s.get())) {
std::cout << " radius = " << circle->radius << "\n";
}
}
return 0;
}