问题描述
例如我有三个班
class Shape
{
static bool collide(Box * a,Box * b)
static bool collide(Box * a,Sphere * b)
static bool collide(Sphere * a,Sphere * b)
};
class Box : public Shape{};
class Sphere : public Shape{};
Shape * a = new Box();
Shape * b = new Sphere();
Shape::collide(a,b);
编译器引发并出错。
如何在不添加太多逻辑的情况下自动向下转换作为参数给出的对象?
解决方法
编译器不能自动转换对象,你必须手动转换它们,例如:
class Box;
class Sphere;
class Shape
{
virtual ~Shape(){}
static bool collide(Shape *a,Shape *b);
static bool collide(Box *a,Box *b);
static bool collide(Box *a,Sphere *b);
static bool collide(Sphere *a,Sphere *b);
};
class Box : public Shape{};
class Sphere : public Shape{};
bool Shape::collide(Shape *a,Shape *b)
{
if (Box *a_box = dynamic_cast<Box*>(a))
{
if (Box *b_box = dynamic_cast<Box*>(b))
return collide(a_box,b_box);
if (Sphere *b_sphere = dynamic_cast<Sphere*>(b))
return collide(a_box,b_sphere);
}
else if (Sphere *a_sphere = dynamic_cast<Sphere*>(a))
{
if (Sphere *b_sphere = dynamic_cast<Sphere*>(b))
return collide(a_sphere,b_sphere);
}
return false;
}
bool Shape::collide(Box *a,Box *b) { ... }
bool Shape::collide(Box *a,Sphere *b) { ... }
bool Shape::collide(Sphere *a,Sphere *b) { ... }
Shape * a = new Box();
Shape * b = new Sphere();
Shape::collide(a,b);
不用说,随着新形状的添加,这会变得有点乏味。您应该改为向 virtual
本身添加一个 Shape
方法,并让派生类覆盖它以根据需要处理不同的类型,例如:
class Shape
{
virtual ~Shape(){}
virtual bool collide(Shape * b) { return false; };
};
class Box : public Shape{
bool collide(Shape * b) override {
if (Box *b_box = dynamic_cast<Box*>(b)) {
return ...;
}
if (Sphere *b_sphere = dynamic_cast<Sphere*>(b)) {
return ...;
}
return Shape::collide(b);
};
};
class Sphere : public Shape{
bool collide(Shape * b) override {
if (Sphere *b_sphere = dynamic_cast<Sphere*>(b)) {
return ...;
}
return Shape::collide(b);
};
};
Shape * a = new Box();
Shape * b = new Sphere();
a->collide(b);