因此假设我有一个基类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
Monster
和Grass
类的列表,但是Grass
不可碰撞,但是,让我们说它需要与其他班级一起留在阵列中。我如何确定数组中的类是Collidable
?
(如果我在某种程度上偏离关键,我会道歉,但我最近一直在研究和研究一堆面向对象的事情,所以我仍处于学习阶段。)
答案 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_of和a 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();
}
}
foo(void)
is deprecated in C++,它是来自C的残余。virtual
确保以正确的顺序调用析构函数。std::vector
。shared_ptr
这样的智能指针。