2012-05-07 56 views
4

在我的程序中,我有一个名为Entity的类。另一个类入侵者继承实体。因为我想拥有4种不同的入侵者,所以我宣布从Invader继承的Invader1,Invader2,Invader3和Invader4类。现在,我宣布一个实体指针型向量来存储像所有的入侵者:检查派生类的类型

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等。

我该如何做到这一点?

+6

在运行时需要知道类表明设计不好。你究竟在做什么? –

回答

6

在C++中有很多方法可以做到这一点,但根本的问题是,一旦你必须开始查询应该是多态的容器中的元素,你可能会放弃使用多态性的想法。具有多态元素集合的全部意义在于,您可以将它们全部对待。所以如果你有一个vector<Entity*>你应该只把它的元素当作Entity* s。如果您发现需要拨打Entity上类似Invader的功能,则最好还是持有容器Invader*(使用与原始容器相同的指针)。

+0

我完全同意。这是利斯科夫原则的全部内容! – ltjax

+0

是的,你是对的。当你尝试使用多态性时,使用类型检查有点令人尴尬。但对于一些罕见的情况,似乎我必须检查类型并使对象的功能不同。我试图改善我的计划的结构。 Thx的帮助! – Tony

3

你可以检查是否dynamic_cast<Invader*>(entities->at(index))回报不NULL(因为它会导致NULL指针当指针并未指向一个对象,它的类是从Invader派生)。

有关文档,请参阅this link

2

创建一个Invader类,它继承自Entity。请让您的Invader1,Invader2等继承自Invader

然后,您可以添加一个virtual bool IsInvader() const;返回在EntityfalseInvadertrue

+1

然后每次你编写一个派生自'Entity'的类时,在'Entity'中添加一个'isWhatever()'? – juanchopanza

+0

@juanchopanza'virtual const char * getClassName()const;'然后呢? – moooeeeep

+1

@moooeeeep它几乎一样糟糕。必须查询“多态”集合中每个元素的设计失去了多态的所有好处,并且根本不可扩展。 – juanchopanza

1

只是问这个问题通常意味着你实际上在你的界面中缺少一个虚拟功能。

如果你有这样的:

您可以几乎可以肯定在你的侵略者类中添加

virtual void tryInvade() {/* normally, entities don't invade*/} 
在实体

virtual void tryInvade() {invade(); /*but invaders do!*/} 

重构它。

另一种选择是永远不会“失去”实体的类型。如果你不想在这种情况下使用虚函数,那么很可能你不应该通过引用它们的基类指针来存储这些实体,而是作为你实际想要使用的类的指针。也就是说,您只需将实体的类型保留在周围,而不要稍后再问。这可能是一个迹象,你不应该继承tho,因为你会违反liskov substition principle各自的存储。