在C++中了解子类的类

Pau*_*ulG 12 c++ oop polymorphism inheritance

我至少在7年内没有完成C++,而且在C++项目中我突然陷入了困境.我想要一些以下指导:

我有一个名为Animal的类,我有3个继承自Animal:Cat,Dog和Bird的类.我创建了一个列表对象,并使用它来存储类型Animal.

这个列表可以包含猫狗和鸟,当我迭代这个动物列表时,我想知道每个动物的直接类型(无论是猫,狗还是鸟).

当我说它typeid(animal).name();给了我动物,这是真的,但我想知道什么样的动物.

有任何想法吗??我应该使用枚举吗?

Mar*_*cin 21

你几乎肯定不想知道.你应该做的是宣称与这些动物互动的虚拟方法.

如果您需要专门对它们进行操作,您可以使用访问者模式传递访问者对象或在每个具体类中运行正确的数据.如果你坚持使用标签(我强调这是第三种选择 - 其他两种解决方案将使你的代码更加清晰),请调用一个虚拟方法classname返回类型标识符(无论是字符串还是int或其他).

如果您有一个对象类型数组,而不是指针类型,请注意关于切片的要点.如果你在7年内没有使用C++,你可能不会意识到模板使用的增长使语言变得更好.查看诸如boost之类的库以查看可以执行的操作,以及模板如何允许您编写类型推断的通用代码.

  • 虽然我完全赞同你的回答,但我仍然会指出`typename`是C++中的保留关键字. (6认同)

Aes*_*ete 16

Dog* dog = dynamic_cast<Dog*>(myAnimalPointer);
if (dog == NULL)
{ 
    // This animal is not a dog.
}
Run Code Online (Sandbox Code Playgroud)

  • 我想说,到目前为止,这是对这个问题的唯一实际"回答".虽然虚拟功能的想法也有效.+1 (3认同)
  • 或者不可抗拒的流线型形式...`if (Dog* dog = dynamic_cast&lt;Dog*&gt;(myAnimalPointer)) ...`。但是,一般来说这不一定是*正确*的答案 - 如果以后有进一步派生的`Doberman`和`Poodle`类,则此代码将继续编译和运行,而不会告诉最派生的名称。好的,但问题中的层次结构非常有限。 (2认同)

Mar*_*k B 11

需要知道一个特定的具体对象类型通常是C++中的设计气味所以我建议你不要尝试这样做.

相反,在其中创建一个抽象(纯虚拟)界面Animal,描述您希望动物拥有的功能.然后,您可以利用动态调度来调用该功能,甚至无需知道对象的动态类型.如果需要,您始终可以在子类中创建私有非虚拟辅助函数.

另请注意,您需要将Animal(智能)指针存储在容器中,而不是存储在值中.如果按值存储它们,它们将在插入列表时被切片,从而丢失动态类型信息.

正如@Marcin指出的那样,如果你真的需要在特定的子类上调用特定的方法,那么使用访问者模式进行双重调度可能是一种更好的方法.