《C++ Primer plus》学习笔记之”RTTI”

1. 运行阶段类型识别(RTTI)

RTTI是运行阶段类型识别的简称,它为程序在运行阶段确定对象的类型提供了一种标准方式。组要注意的是,他们只适用于包含虚函数的对象。

RTTI主要包含三个元素:dynamic_cast,typeid和typeinfo

(1) dynamic_cast

该操作符将使用一个指向基类的指针来生成一个派生类的指针;如果生成失败,则返回0—空指针。

dynamic_cast不能回答“指针指向的是哪类对象”,但能回答“是否可以安全地将对象的地址赋给特定的类型的指针”。举例:

1
2
3
4
5
class Grand{…};
 
class Superb: public Grand{…};
 
class Magnificent: public Superb {…};

假设有以下指针:

1
2
3
4
5
Grand *pg = new Grand;
 
Grand *ps = new Superb;
 
Grand *pm = new Magnificent;

对于以下转换:

1
2
3
4
5
Magnificent *p1 = (Magnificent *) pm;   //#1
 
Magnificent *p2 = (Magnificent *) pg;   //#2
 
Superb *p1 = (Magnificent *) pm;    //#3

哪些是安全的呢?很明显,#1和#3是安全的,#2是不安全的,因为派生类中可能存在基类中并没有的数据成员和函数。

怎样知道类型转换是否安全呢?可使用dynamic_cast,表达式为:dynamic_cast<Type *>(pt)

如:

1
Superb *pm = dynamic_cast <Superb *>(pg);

(2) typeid

返回一个指出对象类型的值。可用于判断两个对象是否为同类型。与sizeof类似,可接受两种参数:类名和结果为对象的表达式。

(3) type_info

typeid返回的是对type_info的引用。type_info重载了==和!=操作符,可使用这些操作符对类型进行比较,例如,如果pg指向的是一个Dog对象,则表达式:

typeid(Dog) == typeid(*pg) 的结果为bool值true。

2. 类型转换操作符

C语言中能够的类型转换操作符过于松散,如:

1
2
3
4
5
6
7
8
9
10
11
struct Data { double Data[200];};
 
struct Junk{ int junk[200]};
 
Data d={2.5, 3.2,2.1};
 
char * pch = ( char *)(&d);
 
char ch = char (&d);
 
Junk *pj = (Junk*)(&d);

上述转换中,哪些有意义?除非不讲理,否则任何一种均有意义。

对于这种松散情况,C++更为严格地限制允许的类型转换,并添加了4个类型转换操作符:dynamic_cast(前面已经介绍),const_cast,static_cast,reinterpret_cast。

(1)const_cast:去掉const和volatile标签,如:

1
2
3
4
5
const int a = 5;
 
const int * b = const_cast < int *>(&a);
 
*b = 6; //ok!!!

提供该操作符的原因是,有时候可能需要这样一个值,他在大部分情况下是常量,而有时又是可以修改的。

(2) static_cast: 使用:static_cast<type_name> (expression);

仅当type_name可被隐式转换为expression所属的类型或者expression可被隐式转换为type_name所属的类型时,上述转换才合法。

设High是Low的基类,而Pond是一个无关的类,则:

1
2
3
4
5
6
7
8
9
10
11
High high;
 
Low low;
 
……
 
High *pb = static_cast <High *>(&low); //valid
 
Low *pl = static_cast <Low *>(&high); //valid
 
Pond *pp = static_cast <Pond*>(&low); //invalid

static可用将整数转化为枚举类型,将枚举类型转化为整数类型,将double转为int,将float转为long等

(3) reinterpret_cast:用于天生危险的类型转换,有时程序员必须做一些依赖于实现的,令人生厌的操作。如:

1
2
3
4
5
6
7
struct dat { short a; short b;};
 
long value=0Xa224b118;
 
dat *pd = reinterpret_cast <dat *>(&value);
 
cout<<pd->a;

原创文章,转载请注明: 转载自董的博客

本文链接地址: http://dongxicheng.org/cpp/cpp-rtti/

你可能感兴趣的:(C++,学习笔记,RTTI,Plus,Primer,运行阶段类型识别)