以下面的C++为例。
vector<Animal> listAnimal;
class Fish : Animal ...
class Mammal : Animal ...
class Bird : Animal ...
如果我然后将它们全部添加到列表中,然后任意将它们从列表中取出,我将不知道我正在处理哪个子类。我在 Java 中可以执行 getClass()
或 thefish instanceof Fish
。我如何在 C++ 中执行此操作?
最佳答案
您不需要知道您正在处理的是什么类型的子类。如果您需要检查正在处理的类的类型,那么您就没有正确地进行多态性处理。多态性的全部意义在于减少 if 并使您的代码更加灵活。
有些情况需要知道,可以用RTTI为了那个原因。但是我建议不要这样做,尤其是当您需要大量性能时(例如游戏或图形程序)。
使用 typeid
运算符获取有关类的信息,并确定类是否为特定类型。
例如:
Animal* animal1 = new Cat;
if(typeid(animal1) == typeid(Cat))
{
cout << "animal1 is a: " << typeid(Cat).name();
}
然后使用 static_cast
将其向下转换。
Animal* animal1 = new Cat;
if(typeid(animal1) == typeid(Cat))
{
Cat* cat = static_cast<Cat*>(animal1);
cat->scratchTheLivingHellOutOfYou();
}
或者,您可以使用 dynamic_cast
,它更安全,但比 typeid/static_cast 慢得多。像这样:
Animal* animal1 = new Cat;
if(Cat* cat = dynamic_cast<Cat*>(animal1)
{
cat->scratchTheLivingHellOutOfYou();
}
编辑:
dynamic_cast
比较慢,因为它必须做一些额外的工作,而不仅仅是测试它是否是特定类型和转换。即 dyanmic_cast
不等同于 typeid/static_cast
,但几乎是。
想象一个比 2 层更深的层次结构,例如:
class Animal { /* ... */ }; // Base
class Cat : public Animal { /* ... */ }; // 2nd level
class Tiger : public Cat { /* ... */ }; // 3rd level
假设在 Cat 类中,调用了一个特定于所有 Cats 的方法:scratchTheLivingHellOutOfYou()
。我们还可以这么说:我有一个 Animals 列表,我想为列表中的每只 Cat 调用 scratchTheLivingHellOutOfYou()
(这包括派生自 Cat 类的类)。如果使用 typeid
运算符和 static_cast
,这将无法达到要求,因为 typeid
只检查当前类型而不关心关于层次结构。为此,您必须使用 dynamic_cast
,因为它将检查类是否派生自基类,然后相应地向上/向下转换层次结构。
你可以在 C++ 中看到这个简单的例子,here .这是程序的输出:
USING TYPEID
*scratch*
meoyawnn!
RAWR
USING DYNAMIC_CAST
*scratch*
meoyawnn!
*scratch*
RAWR
因此,您可以清楚地看到 dynamic_cast
比简单的 typeid
和 static_cast
做了更多的工作。由于 dynamic_cast
查找层次结构以查看是否 它是特定类型。简单地说... dynamic_cast
可以在层次结构中向上和 转换。而 typeid
和 static_cast
只能将层次结构向下转换为特定类型。
我想我会提到,如果 dynamic_cast
失败,它将返回 NULL 指针,或者如果您将它与引用一起使用,则会抛出异常。
注意事项:
- 如果您确实需要性能并且需要检查多态对象的类型,我建议寻找 RTTI 的替代方法,例如使用模板/宏或其他任何方法来识别类。
dynamic_cast
只应在您不确定对象将是您要转换成的类型时使用。如果你,作为一个程序员,知道你正在转换的任何东西都是 100% 的类型,那么使用static_cast
,例如如果您知道 animal1 将要成为一只Cat
,那么static_cast
更合适。
关于C++ 继承 - getClass() 等效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14531978/