C++ RTTI的使用

这里我们给出一个使用RTTi的例子;

考虑一个类层次,我们希望为它实现 operator==相等操作符:如果两个对象的给定数据成员集合的值相同,则它们就相等。

每个派生类可以增加自己的成员,当然,测试相等的时候也要包含这些数据。

对于类层次中有两个类型(一个基类,一个派生类),按照一般的方法,我们就需要实现以下四个函数。

bool operator==(const Base&, const Base&bool operator==(const Derived&, const Derived&bool operator==(const Base&, const Derived&bool operator==(const Derived&, const Base&)

但是如果类层次中有几个类型,必须定义的操作符的数目就迅速扩大---3个类型需要9个操作符,4个类型就需要16个操作符~~
那么,我们有没有较好的办法来解决这一问题呢?这里我们采用RTTi

只重载一个Animal基类的==操作符
为每个类(包括派生类)实现 equal函数,这是一个虚函数。

在编写代码之前,我们要搞清楚,两个类相等 的前提是 首先它们的类型相同,其次它们的成员也相同
在这里,首先做几点说明,以下的类中,Animal是基类,Cat,Dog是其派生类。

代码如下:

 1 #include <iostream>
 2 #include <typeinfo>
 3 #include <string>
 4 using namespace std;
 5 
 6 class Animal
 7 {
 8     public:
 9         virtual bool equal(const Animal &other)const = 0;11 };
12 
13 class Cat:public Animal
14 {
15     public:
16         bool equal(const Animal &other)const
17         {
18             if(const Cat *pc = dynamic_cast<const Cat*>(&other))
19             { return name_ == pc->name_; }
20             return false; 
21         }
22     private:
23         string name_;
24 };
25 
26 class Dog:public Animal
27 {
28     public:
29         bool equal(const Animal &other)const
30         {
31             if(const Dog *pd = dynamic_cast<const Dog*>(&other))
32             { return name_ == pd->name_; }
33             return false;
34         }
35     private:
36         string name_;
37 };
38 
39 bool operator==(const Animal &a, const Animal &b)
40 {
41     return typeid(a)==typeid(b)&&a.equal(b);
42 }
43 
44 
45 int main(int argc, const char *argv[])
46 {
47     Cat c;
48     Dog d;
49     Animal *pa = &c;
50    
51     cout <<( *pa == c) << endl;//1
52     cout <<( *pa == d) << endl;//0
53     return 0;
54 }

这里我们做以下几点说明;

首先是==operator的重载 

1 bool operator==(const Animal &a, const Animal &b)//Animal中有虚函数
2 {
3      return typeid(a)==typeid(b)&&a.equal(b);//运行时绑定
4 }

这里利用了&&的短路特性,即:如果两个对象的类型不同(Cat,Dog),那么该语句直接返回false,不再继续比较后面的条件。

然后我们再看Cat中的equal函数:

 bool equal(const Animal &other)const
        {
            if(const Cat *pc = dynamic_cast<const Cat*>(&other))
            { return name_ == pc->name_; }
            return false; 
        }   

if语句中用到了dynamic_cast 强制转换,而这个强制转换总是成功的,那么这个强制转换还是必要的吗?答案是肯定的。原因如下:

如果不进行强制转换,那么可能造成不能访问函数的右操作数的派生类成员。例如other类为Animal,若不进行“向下塑形(运行时绑定)”转化,则otherr不能访问Cat的成员name_。
原文地址:https://www.cnblogs.com/xfxu/p/4012383.html