调用对象方法传递超类期望子类

Posted

技术标签:

【中文标题】调用对象方法传递超类期望子类【英文标题】:Calling object method passing superclass where subclass expected 【发布时间】:2021-01-12 15:05:24 【问题描述】:

例如我有三个班级

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);

编译器引发错误。

如何在不添加太多逻辑的情况下自动向下转换作为参数给出的对象?

【问题讨论】:

听起来你需要一些polymorphism 【参考方案1】:

编译器不能自动转换对象,你必须手动转换它们,例如:

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);

【讨论】:

以上是关于调用对象方法传递超类期望子类的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在超类对象上调用子类的方法?

Java多态如何调用子类对象的超类方法

超类中子类的C++调用方法?

将超类作为参数传递给期望子类的方法

在Python 3中,超类可以多态地调用子类的构造函数

为啥在声明子类的对象时会调用超类的构造函数? (爪哇)