如果它们继承了抽象基类,则确定何时在某些类上使用函数

时间:2014-06-06 18:25:00

标签: c++ oop inheritance abstract-class multiple-inheritance

因此假设我有一个基类Object和一个抽象基类Collidable。 (Object包含位置信息,Collidable包含virtual void Collide(Object object) = 0。然后会有继承Object的子类,但只有某些子类会继承Collidable所以我的问题是,如果其中一个可碰撞的子类要查看Object个继承类的列表,那么它如何确定它们是否也继承Collidable以便它们相互碰撞而不是与不可碰撞的物体?

(为了更直观地看待我的问题)

class Object
{
protected:
    Position myPosition;

public:
    Object(void);
    ~Object(void);
}

class Collidable
{
protected:
/* ... */

public:
    virtual void Collide(Object& object) = 0;

    Collidable(void);
    ~Collidable(void);
}

class Grass : public Object
{
private:
/* ... */

public:

    Grass(void);
    ~Grass(void);
}

class Wall : public Object, public Collidable
{
private:
/* ... */

public:
    virtual void Collide(Object& object) { /* Collide logic */ }

    Wall(void);
    ~Wall(void);
}

class Monster : public Object, public Collidable
{
private:
/* ... */

public:
    virtual void Collide(Object& object) { /* Collide logic */ }

    Monster(void);
    ~Monster(void);
}

int main()
{
    Monster creature;
    Object* objects[] = { /* list of Grass, Wall, and Monster classes */ };

    for(int i = 0, i < objects.size(); i++)
    {
        //Logical error: not every object is collidable
        creature.Collide(&objects[i]);
    }
}

所以在这里,我有一个Wall MonsterGrass类的列表,但是Grass不可碰撞,但是,让我们说它需要与其他班级一起留在阵列中。我如何确定数组中的类是Collidable

(如果我在某种程度上偏离关键,我会道歉,但我最近一直在研究和研究一堆面向对象的事情,所以我仍处于学习阶段。)

2 个答案:

答案 0 :(得分:3)

(注意:一些建议,特别是如果你处于学习阶段 - 如果你确保你的示例代码编译了一些基线,那么人们就可以更容易地调整你所询问的部分的工作版本编译器警告也是有启发性的,所以你可以提前发现错误...比如你在Object上错过了一个虚拟的析构函数。如果我们不知道你是否知道为什么那么糟糕,那么这可能会分散注意力。不。)


您尝试通过继承的类将对属性编码为对象,然后在运行时检查这些属性。

技术上可以使用Run-Time-Type-Information,使用dynamic_cast<>并注意它何时返回空指针。

Grass grass;
cout << dynamic_cast<Collidable *>(&grass) << "\n";

Monster monster;
cout << dynamic_cast<Collidable *>(&monster) << "\n";

当我跑步时,我得到:

0
0xbfabb10c

所以草可以施放,怪物不能。这个简化的案例也会产生编译器警告:

  

警告:'草草'到'类可碰撞*'的dynamic_cast永远不会成功[默认启用]

但这并不是C ++方法的真正意图。最好按照@ bstar55建议的方式进行思考,并在所有对象上使用虚拟isCollidable(),其中一些返回false。或者甚至考虑一个对象不是“可碰撞的”和一个总是失败的碰撞测试之间的区别。这取决于系统的设计。

不是尝试在运行时导航类层次结构,而是更好地关注在执行编译时工作时使用继承或“特征”。这才是真正的美丽。但这是一个很深刻的话题。我只想指出像std::is_base_ofa list of other type traits这样的几个部分。

答案 1 :(得分:1)

您可以dynamic_cast确定object是否可转换为Collidable,如下例所示:

int main()
{
  std::vector<Object*> objects{ new Monster(), new Wall(), new Grass() };

  for (auto i : objects){
    if (dynamic_cast<Collidable*>(i)) dynamic_cast<Collidable*>(i)->Collide();
  }
}

Display

建议:

  1. foo(void) is deprecated in C++,它是来自C的残余。
  2. 使用继承时,必须使the destructor of base classes virtual确保以正确的顺序调用析构函数。
  3. 请勿使用C原始数组,而是使用std::vector
  4. 与上面的例子不同,不要使用原始指针,而应使用像shared_ptr这样的智能指针。