在我的程序中,我有一个名为Entity的类。另一个类Invader继承实体。由于我想拥有4种不同类型的入侵者,因此我声明了继承自Invader的Invader1,Invader2,Invader3和Invader4类。现在我声明一个Entity指针类型向量来存储所有入侵者,如:
entities.push_back(new Invader4());
entities.push_back(new Invader3());
entities.push_back(new Invader2());
entities.push_back(new Invader1());
entities.push_back(new Invader0());
当我在运行时检查实体中元素的类型时,请说
typeid(*entities->at(index))
它可能会返回4种入侵者中的一种。在实体中还有其他继承实体的对象。所以我只想检查对象的类型是否是Invader,我不想知道它是Invader1,Invader2等。
我怎么能做到这一点?
答案 0 :(得分:6)
在C ++中有很多方法可以做到这一点,但基本问题是,一旦你必须开始查询应该是多态的容器中的元素,你可能会放弃使用polimorphism的想法。拥有多态元素集合的全部意义在于,您可以对它们进行相同的处理。因此,如果您有vector<Entity*>
,则只应将其元素视为Entity*
。如果您发现需要在Invader
上调用某些类似Entity
的函数,那么最好还容纳Invader*
的容器(使用与原始容器相同的指针) )。
答案 1 :(得分:3)
您可以检查dynamic_cast<Invader*>(entities->at(index))
是否返回NULL
(因为当指针未指向其类派生自{{1}的对象时,它会导致NULL
指针})。
有关文档,请参阅this link。
答案 2 :(得分:2)
创建一个继承自Invader
的{{1}}类。让您的Entity
,Invader1
等类继承自Invader2
。
然后,您可以添加Invader
,在virtual bool IsInvader() const;
中返回false
,在Entity
中添加true
。
答案 3 :(得分:1)
只是问这个问题通常意味着你实际上错过了界面中的虚拟功能。
如果你有类似的话:
if (myEntity->Type() == TypeInvader)
{
static_cast<Invader*>(myEntity)->invade();
}
你几乎可以肯定通过添加
来重构它virtual void tryInvade() {/* normally, entities don't invade*/}
在你的实体和
中virtual void tryInvade() {invade(); /*but invaders do!*/}
在你的Invader课程中。
另一种选择是永远不会“失去”你的实体类型。如果您不想在这种情况下使用虚函数,那么您可能不应该通过引用它们的基类指针来存储这些实体,而应该作为指向您实际想要使用的类的指针。也就是说,您只需保留实体的类型,而不是稍后要求它。这可能表明您不应该使用继承,因为您违反了liskov substition principle相应的存储空间。