运行时类型信息(Run-time Type Information,RTTI)提供了在程序运行时刻确定对象类型的方法,是面向对象程序语言为解决多态问题而引入的一种语言特性。由于多态的要求,C++指针或引用可能与他们实际代表的类型不一致(如基类指针可以指向派生类对象),当将一个多态指针转换为其 实际指向类型对象时,就需要知道对象类型信息。
在C++中,用于支持RTTI的运算符有:dynamic_cast, typeid, type_info.
#include <iostream>
#include <typeinfo>
using namespace std;
int main(void){
int i = 10;
cout << typeid(i).name() << endl;
cout << typeid(int).name() << endl;
int* p1[10]; //指针数组 p1数组中存放10个元素 这10个元素都是int* 类型的
int (*p2)[10]; //指针变量 p2指向数组类型的数据,数据是有10个元素的int型数组
cout << typeid(p1).name() << endl;
cout << typeid(p2).name() << endl;
return 0;
}
myubuntu@ubuntu:~/lv19/cplusplus/dy05$ ./a.out
i
i
A10_Pi
PA10_i
#include <iostream>
#include <typeinfo>
using namespace std;
class A {
public:
virtual void foo(void) {}
};
class B : public A {
public:
void foo(void) {}
};
class C : public A {
public:
void foo(void) {}
};
void func(const A& a){
if(typeid(a) == typeid(B)){ //判断创建的对象 是什么类型的
cout << "B" << endl;
} else if(typeid(a) == typeid(C)) {
cout << "C" << endl;
}
}
int main(void) {
B b;
C c;
func(b);
func(c);
return 0;
}
myubuntu@ubuntu:~/lv19/cplusplus/dy05$ ./a.out
B
C
强制类型转换运算符,主要用于具有多态继承关系父子类指针或引用之间的显式转换。
语法格式:
dynamic_cast <目标类型> (表达式)
#include <iostream>
#include <typeinfo>
using namespace std;
class Base {
public:
virtual void foo(void) {}
};
class Derived : public Base {
public:
void foo(void) {}
};
int main(void){
Base *pb, b; //基类
Derived *pd, d; //子类
pd = &d;
pb = pd; // Base * <------- Derived * 向上造型 隐式转换 编译时完成 这种转换不安全 后期排查错误不方便
pb = dynamic_cast<Base *>(&d); //显示转换 向上造型 运行时完成的
return 0;
}
向下造型时,动态类型转换会对所需转换的基类指针或引用做检查,如果其目标确实为期望得到的子类类型的对象,则转换成功,否则转换失败
#include <iostream>
#include <typeinfo>
using namespace std;
class Base {
public:
virtual ~Base() {}
};
class Derived : public Base {
public:
void foo(void) {
cout << "Derived foo()" << endl;
}
};
int main(void){
Base *pb, b;
Derived *pd, d;
pb = &b;
/*
* 语法上不报错:具有父子关系 具有多态特性
* 该转换不合理:在运行期间完成转换 转换失败 C++认为不安全
* */
pd = dynamic_cast<Derived *>(pb);
if(pd) cout << "ok" << endl;
else cout << "error" << endl;
// pd = reinterpret_cast<Derived *>(pb);
// pd = (Derived *)pb; //C风格强转 可以编译通过
// pd->foo(); //有问题,pd 已经转换成基类的类型了 基类中没有foo()函数
pb = &d; //向上造型 缩小了访问范围
pd = dynamic_cast<Derived *>(pb); //编译通过 也是合理转换
if(pd) cout << "ok" << endl;
else cout << "error" << endl;
return 0;
}