RTTI在C++继承中的运用

  
RTTI: Run-Time Type Identification 运行时刻类型识别。为了支持RTTI,在C++中,提供了两个操作符:
1. dynamic_cast 操作符,它允许在运行时刻进行类型转换,从而使程序能够在一个类层次结构中安全地转换类型,把基类指针(引用)转换为派生类指针(引用)。
2. Typeid操作符,它指出指针或者引用指向的对象的实际派生类型。
 
dynamic_cast操作符
dynamic_cast 被用来执行从基类指针到派生类指针的安全转换,因此常常被称为安全的向下转换(downcasting)。当我们必须使用派生类的特性,而该特性有没有出现在基类中的时候,我们常用dynamic_cast。
一般情况下,我们通过虚拟函数的机制实现利用指向基类类型的指针来操纵派生类对象。如下所示的类层次结构:
class employee
{
public:
virtual int Salary();
};
 
class manager : public employee
{
public:
int Salary();
};
 
class programmer : public employee
{
public:
int Salary();
};
我们可以定义一个指向基类的指针 employee * p,该指针可以指向manager类也可以指向programmer类,根据p指向的类型,分别调用manager或者programmer的salary函数。
       但是,假如我们想为programmer增加一个新的成员函数bonus,能够通过指向基类的p指针来调用,那么,可以修改基类定义,重新编译程序,从而实现所需功能。
class employee
{
public:
virtual int Salary();
virtual int bonus();
};
但是万一该基类的定义是第三方库提供商提供的,我们无法重新修改编译,或者我们不想修改基类的定义。为了扩展这个类库,实现基类指针能够调用programmer的bonus功能,就可以使用dynamic_cast。
我们可以直接在programmer中对该类进行扩展,增加bonus的定义,而不需改动基类。
class employee
{
public:
virtual int Salary();
};
 
class manager : public employee
{
public:
int Salary();
};
 
class programmer : public employee
{
public:
int Salary();
int bonus();
};
 
我们可以这样利用dynamic_cast操作符,在运行时刻判断指针所知的类型是否为指定的类型,从而判断是否可以调用扩展的功能函数。
例如,一个外部函数,void payroll(employee *pe),我们可以这样定义:
                                      programmer  *pm = dynamic_cast <programmer *>(pe);
                                      if(pm)
                                      {
                                                cout << "the programmer's bonus is: " << pm->bonus() << endl;
}
else
{
                                            cout << "the point is not point to programmer object!/n" ;
                                                cout << "the salary is :" << pe->Salary() << endl;
}
……
         dynamic_cast为用户在不方便或者不想改变基类的情况下,扩展派生类的特性提供了一种替代机制。但是这种机制比虚拟函数机制容易出错,需要小心运用。如果dynamic_cast返回一个不为零的指针,则类型转换成功,否则转换失败,返回0。
 
typeid操作符
typedi在程序中可以获取一个表达式的类型。
例如:
 int iobj;
 cout << typeid(iobj).name() << endl; //打印 int
 cout << typeid(8.16).name() <<endl; //打印 double;
如果表达式是一个类类型,并且包含有一个或者多个虚拟函数,则typeid哕指出底层对象的派生类型。例如:
 programmer pobj;
 employee &re = pobj;
 cout << typeid(re).name() << endl; // 打印显示“ class programmer”
具体可以用下面的例程来论证:
#include <typeinfo>
#include <iostream.h>
class employee
{
public:
         virtual int Salary();
};
 
class manager : public employee
{
public:
         int Salary();
};
 
class programmer : public employee
{
public:
         int Salary();
         int bonus();
};
 
class company
{
public:
         void payroll(employee *pe);
};
 
int employee::Salary()
{
         return 3000;
}
 
int manager::Salary()
{
         return 5000;
}
 
int programmer::Salary()
{
         return 4000;
}
 
int programmer::bonus()
{
         return 6000;
}
void company::payroll(employee *pe)
{
         programmer *pm = dynamic_cast<programmer *>(pe);
         if(pm)
         {
                   cout << "the programmer's bonus is: " << pm->bonus() << endl;                 
         }
         else
         {
                   cout << "the point is not point to programmer object!/n" ;
                   cout << "the salary is :" << pe->Salary() << endl;
         }
         return;
}
 
int main()
{
         company *pCompany = new company;
         employee *pe = new programmer;
         employee *pm = new manager;
         pCompany->payroll(pe);
         pCompany->payroll(pm);
         cout << "================================================" << endl;
 
         employee &re = *pe;
         employee &rm = *pm;
 
         int iobj;
 
         cout << typeid(iobj).name() << endl;
         cout << typeid(8.16).name() << endl;
         cout << "================================================" ;
 
        
         cout <<"/n/n/n";
         cout << "The type of the re poject: " << typeid(re).name() << endl;
         if(typeid(pm) == typeid(employee *))
                   cout << "the same class !/n";
         if(typeid(pm) == typeid(manager *))
                   cout << "also the same class !/n";
         cout << " pm : " << typeid(pm).name() << endl;
         cout << " employe * : " << typeid(employee *).name() << endl;
         cout << " manager *: " << typeid(manager *).name() <<endl;
        
         cout << " *pm : " << typeid(*pm).name() << endl;
         delete pm;
         delete pCompany;
         delete pe;
         return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值