问题描述
以下列C ++为例。
vector< Animal> listAnimal;
类鱼:动物...
类哺乳动物:动物...
类鸟:动物...
如果我将它们全部添加到列表中,然后从列表中随意抓取我不知道我处理哪个子类。我在Java我可以做 getClass()
或 thefish instanceof Fish
。如何在C ++中执行此操作?
您不应该需要知道什么类型的子类与。如果你需要检查你正在处理的类的类型,你不会做多态性。多态性的全部是减少if和使你的代码更加灵活。
但是有些情况下你需要知道,你可以使用,但我建议不要,特别是如果你需要很多性能(如游戏或图形程序)。
使用 typeid
运算符获取有关类的信息,是一种特定类型。
例如:
= new Cat;
if(typeid(animal1)== typeid(Cat))
{
cout< animal1 is a:<< typeid(Cat).name();
}
然后使用 static_cast
动物* animal1 = new Cat;
if(typeid(animal1)== typeid(Cat))
{
Cat * cat = static_cast< Cat *>(animal1);
cat-> scratchTheLivingHellOutOfYou();
}
您可以使用 dynamic_cast
这是更安全,但比typeid / static_cast慢得多。像这样:
动物* animal1 = new Cat;
if(Cat * cat = dynamic_cast< Cat *>(animal1)
{
cat-> scratchTheLivingHellOutOfYou();
}
EDIT:
dynamic_cast
更慢只是因为它需要做一些额外的工作,而不仅仅是测试它是一个特定的类型和铸造。 dyanmic_cast
不等于 typeid / static_cast
,但它几乎是。
想象一下,例如:
class Animal {/ * ... * /}; // Base
/ pre>
class Cat:public动物{/ * ... * /}; //第二级
class Tiger:public Cat {/ * ... * /}; //第三级
假设在Cat类中,调用特定于所有Cats的方法:
scratchTheLivingHellOutOfYou()
让我们还说:我有一个Animal *的列表,我想为列表中的每个Cat调用scratchTheLivingHellOutOfYou()
(这包括从Cat类)。如果使用typeid
运算符和static_cast
,这将无法实现所需的。因为typeid
只检查当前类型,而不关心层次结构。为此,您必须使用dynamic_cast
,因为它将检查类是否派生自基类,然后相应地向上/向下投射层次结构。 p>
您可以看到这个简单的例子,在C ++中,。以下是程序的输出:
使用TYPEID
* scratch *
meoyawnn!
RAWR
使用DYNAMIC_CAST
* scratch *
meoyawnn!
* scratch *
RAWR
因此,您可以清楚地看到
dynamic_cast
比简单的typeid
和static_cast
做更多的工作。由于dynamic_cast
查找hiearchy以查看其是否是特定类型。简单地放置...dynamic_cast
可以沿层次结构投射和。而typeid
和static_cast
只能将层次结构压缩为特定类型。
我想提一下,如果
dynamic_cast
失败,它将返回一个NULL指针,或者如果你使用它引用引发异常。
注意:
- 性能,你需要检查类型的多态对象,我建议找到一个替代RTTI。例如使用模板/宏或其他任何标识类。
dynamic_cast
应该仅在您不确定对象将是您正在转换的类型。如果你作为一个程序员,知道你正在投射的是100%将是那种类型,然后使用static_cast
,例如。如果你知道animal1是是Cat
,那么static_cast
更合适。
Take the following C++ for example.
vector<Animal> listAnimal; class Fish : Animal ... class Mammal : Animal ... class Bird : Animal ...
If I then add them all to the list, and then grab them off the list arbitrary I wont know which subclass I am dealing with. I in Java I could do
getClass()
orthefish instanceof Fish
. How do I do this in C++?解决方案You shouldn't need to know what type a sub-class you're dealing with. You're not doing polymorphism right if you need to check the type of class you're dealing with. The whole point of polymorphism is to reduce if's and make your code a lot more flexible.
However there are some cases where you need to know and you can use RTTI for that, however I recommend to not, especially if you require a lot of performance (such as games or graphics programs).
Use the
typeid
operator to get information about a class, and to determine if a class is a specific type.For example:
Animal* animal1 = new Cat; if(typeid(animal1) == typeid(Cat)) { cout << "animal1 is a: " << typeid(Cat).name(); }
Then use a
static_cast
to cast it down the hiearchy.Animal* animal1 = new Cat; if(typeid(animal1) == typeid(Cat)) { Cat* cat = static_cast<Cat*>(animal1); cat->scratchTheLivingHellOutOfYou(); }
Altenatively you can use a
dynamic_cast
which is much safer, but much slower than a typeid/static_cast. Like so:Animal* animal1 = new Cat; if(Cat* cat = dynamic_cast<Cat*>(animal1) { cat->scratchTheLivingHellOutOfYou(); }
EDIT:
dynamic_cast
is slower simply because it has to do a little extra work than just testing if it's a specific type and casting. i.e.dyanmic_cast
is not equivalent totypeid/static_cast
, but it almost is.Imagine a hiearchy further than 2 levels deep, for example:
class Animal { /* ... */ }; // Base class Cat : public Animal { /* ... */ }; // 2nd level class Tiger : public Cat { /* ... */ }; // 3rd level
Let's say that in the Cat class, a method specific to all Cats is called:
scratchTheLivingHellOutOfYou()
. Let's also say that: I have a list of Animal*'s and I want to callscratchTheLivingHellOutOfYou()
for every Cat in the list (this includes classes that derive from the class Cat). If thetypeid
operator andstatic_cast
is used, this would not achieve what is required. Sincetypeid
only checks for the current type and does not care about the hierarchy. For this, you have to use adynamic_cast
, since it will check if a class is derived from a base-class, and then cast up/down the hierarchy accordingly.You can see this simple example, in C++, here. Here is the output of the program:
USING TYPEID *scratch* meoyawnn! RAWR USING DYNAMIC_CAST *scratch* meoyawnn! *scratch* RAWR
Therefore, you can clearly see that
dynamic_cast
does a lot more work than a simpletypeid
andstatic_cast
. Sincedynamic_cast
looks up the hiearchy to see if it is-a specific type. Simply put...dynamic_cast
can cast up and down the hierarchy. Whereas atypeid
andstatic_cast
can only cast down the hierarchy to a specific type.Thought I'd mention, that if
dynamic_cast
fails it will return a NULL pointer, or throw an exception if you're using it with references.NOTES:
- If you really need performance and you need to check types of polymorphic objects, I recommend finding an alternative to RTTI. Such as using templates/macros or whatever else to identify classes.
dynamic_cast
should only be used if you're not sure the object will be the type you're converting to. If you, as a programmer, know whatever you're casting is 100% going to be that type then usestatic_cast
, e.g. if you know animal1 is going to be aCat
thenstatic_cast
is more appropriate.
这篇关于C ++继承 - getClass()等价?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!