首页 > 代码库 > C++ RTTI的使用

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 Animal14 {15     public:16         bool equal(const Animal &other)const17         {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 Animal27 {28     public:29         bool equal(const Animal &other)const30         {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;//152     cout <<( *pa == d) << endl;//053     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_。

 

C++ RTTI的使用