Reputation: 745
So I've got Shape.h, Rectangle.h, Circle.h and main.cpp.
Shape.h got:
class Shape{
public:
Shape() {};
~Shape() { cout << "Destroy Shape."; };
virtual double getArea() = 0;
virtual double getCircumference() = 0;
};
Rectangle and Circle their respective code.
Now in main.cpp I do
Shape* newRectangle= new Rectangle(4, 8);
Shape* newCircle= new Circle(10);
All fine and dandy so far. Here's where I'm stumped. I know what I have to do, I just don't know HOW to do it.
I'm trying to write a function that checks if a Shape* Object belongs to Circle or not.
It goes something like this
if Shape* object belongs to Object-Type Circle, then
cout << "It's a Circle, bruh!";
else
cout << "Ain't a circle, yo!";
I started after googling with that:
void check(Shape & object){
Circle& checkObject = dynamic_cast<Circle&>(object);
}
The function in main will be called via:
check(*newRectangle);
check(*newCircle);
But I haven't got a clue how to go on :(. Any help and explanation is appreciated. Thank you!
Upvotes: 2
Views: 104
Reputation: 726499
You can do it by dynamically casting the Shape
pointer to a pointer of desired type, and checking for nullptr
:
if (dynamic_cast<Circle*>(object)) {
cout << "It's a Circle, bruh!";
}
This requires that Runtime Type Information is turned on, and that your object has at least one virtual function (it does).
Note 1: if you have to do something like that, see if you could change your design so that you wouldn't have to do this. For example, you could apply a multiple dispatch pattern, such as Visitor, to avoid this check:
struct ShapeVisitor {
virtual ~ShapeVisitor() {}
virtual void visitCircle(const Circle* circle);
virtual void visitRectangle(const Rectangle* rectangle);
};
class Shape{
public:
Shape() {};
virtual ~Shape() { cout << "Destroy Shape."; };
virtual double getArea() = 0;
virtual double getCircumference() = 0;
virtual void Accept(const ShapeVisitor& visitor) = 0;
};
struct Circle : public Shape {
virtual void Accept(const ShapeVisitor& visitor) {
visitor.visitCircle(this);
}
};
struct Rectangle : public Shape {
virtual void Accept(const ShapeVisitor& visitor) {
visitor.visitRectangle(this);
}
};
Now you can print the kind of shape you see like this:
struct PrintTypeVisitor : public ShapeVisitor {
virtual void visitCircle(const Circle* circle) {
cout << "It's a Circle, bruh!";
}
virtual void visitRectangle(const Rectangle* rectangle) {
cout << "It's a Rectangle, bruh!";
}
}
...
PrintTypeVisitor v;
Shape* object = ...
object.Accept(v); // This prints dynamic type of the object
Note 2: You need to make Shape
's destructor virtual.
Upvotes: 4
Reputation: 206567
Try to avoid logic based on derived types. Use virtual
member functions whenever you can.
class Shape {
public:
virtual void print(std::ostream& out) const = 0;
...
};
and implement the function in the derived clases.
class Circle : public Shape {
public:
virtual void print(std::ostream& out) const
{
out << "Got a Circle.\n";
}
....
};
If you cannot solve your problem using a virtual
member function, you'll need to resort to dynamic_cast
.
Shape* shapePtr = <some pointer>;
Circle* circlePtr = dynamic_cast<Circle*>(shapePtr);
if ( circlePtr ) {
// Access Circle functionality.
}
Upvotes: 6