4

在我的程序中,我有一个名为 Entity 的类。另一个类 Invader 继承了 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)) 

它可能会返回四种入侵者中的一种。在实体中还有其他继承实体的对象。所以我只想检查对象的类型是否是Invader,我不想知道它是Invader1,Invader2等。

我怎样才能做到这一点?

4

4 回答 4

6

在 C++ 中有很多方法可以做到这一点,但基本问题是,一旦您必须开始查询应该是多态的容器中的元素,您可能会放弃使用多态的想法。拥有多态元素集合的全部意义在于您可以对它们一视同仁。所以如果你有 avector<Entity*>你应该只把它的元素当作Entity*s。如果你发现你需要Invader在 an 上调用一些类似的函数Entity,那么你最好也持有一个容器Invader*(使用与原始容器相同的指针)。

于 2012-05-07T14:13:34.597 回答
3

您可以检查是否dynamic_cast<Invader*>(entities->at(index))不返回(因为当指针未指向其类派生自的对象时NULL,它会产生一个指针)。NULLInvader

有关一些文档,请参阅此链接

于 2012-05-07T13:55:01.167 回答
2

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

然后,您可以添加 a virtual bool IsInvader() const;which return falseinEntitytruein Invader

于 2012-05-07T13:57:56.977 回答
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!*/}

在你的入侵者课程中。

另一种选择是永远不要“丢失”实体的类型。如果您不想在这种情况下使用虚函数,很可能您不应该通过引用它们的基类指针来存储这些实体,而是作为指向您实际想要使用的类的指针。也就是说,您只需保留实体的类型,而不是稍后再请求它。这可能表明您不应该使用继承,因为您将违反liskov 替换原则各自的存储。

于 2012-05-07T14:12:54.497 回答