C ++继承 - getClass()等价? [英] C++ inheritance - getClass() equivalent?

查看:120
本文介绍了C ++继承 - getClass()等价?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下列C ++为例。

  vector< Animal> listAnimal; 

类鱼:动物...
类哺乳动物:动物...
类鸟:动物...

如果我将它们全部添加到列表中,然后从列表中随意抓取我不知道我处理哪个子类。我在Java我可以做 getClass() thefish instanceof Fish 。如何在C ++中执行此操作?

解决方案

您不应该需要知道什么类型的子类与。如果你需要检查你正在处理的类的类型,你不会做多态性。多态性的全部是减少if和使你的代码更加灵活。



但是有些情况下你需要知道,你可以使用 RTTI ,但我建议不要,特别是如果你需要很多性能(如游戏或图形程序)。



使用 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 
class Cat:public动物{/ * ... * /}; //第二级
class Tiger:public Cat {/ * ... * /}; //第三级
/ pre>

假设在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指针,或者如果你使用它引用引发异常。



注意:




  1. 性能,你需要检查类型的多态对象,我建议找到一个替代RTTI。例如使用模板/宏或其他任何标识类。

  2. 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() or thefish 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 to typeid/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 call scratchTheLivingHellOutOfYou() for every Cat in the list (this includes classes that derive from the class Cat). If the typeid operator and static_cast is used, this would not achieve what is required. Since typeid only checks for the current type and does not care about the hierarchy. For this, you have to use a dynamic_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 simple typeid and static_cast. Since dynamic_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 a typeid and static_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:

  1. 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.
  2. 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 use static_cast, e.g. if you know animal1 is going to be a Cat then static_cast is more appropriate.

这篇关于C ++继承 - getClass()等价?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆