Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.0k views
in Technique[技术] by (71.8m points)

c++ - Calling object method passing superclass where subclass expected

For example i have three classes

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{};

and for example somewhere else i have this piece of code

Shape * a = new Box();
Shape * b = new Sphere();

Shape::collide(a, b);

The compiler raises and error.

How can i automatically downcast objects given as argument without adding too much logic?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The compiler can't cast the objects automatically, you will have to cast them manually, eg:

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

Needless to say, that can get a bit tedious as new shapes are added. You should instead add a single virtual method to Shape itself and let the derived classes override it to handle different types as needed, eg:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...