运行时类型识别(RTTI)#
RTTI(Run-Time Type Identification)允许程序在运行时获取对象的类型信息,主要包括 typeid 运算符和 dynamic_cast 运算符。
Note
注意:本站的 C/C++ 代码风格 参考 Google 风格约定禁止使用 RTTI(dynamic_cast 有一定运行时开销,
大量使用通常意味着设计上的多态使用不当),本页仅作学习参考。
typeid#
#include <iostream>
#include <typeinfo>
using namespace std;
class Person {
protected:
string name;
public:
Person(string name = "") : name(name) {};
virtual ~Person() {}
string getInfo() { return name; }
};
class Student : public Person {
string studentid;
public:
Student(string name = "", string sid = "") : Person(name), studentid(sid) {};
string getInfo() { return name + ":" + studentid; }
};
int main() {
string s("hello");
cout << "typeid.name of s is " << typeid(s).name() << endl;
cout << "typeid.name of std::string is " << typeid(std::string).name() << endl;
cout << "typeid.name of Student is " << typeid(Student).name() << endl;
if (typeid(std::string) == typeid(s)) cout << "s is a std::string object." << endl;
return 0;
}
多态与类型转换的陷阱#
下面的例子演示了 C 风格强制转换的危险性:把基类对象强行转换成派生类指针后调用虚函数,会产生未定义行为。
安全的做法是使用 dynamic_cast(配合虚函数)进行向下转换。
#include <iostream>
using namespace std;
class Person {
protected:
string name;
public:
Person(string name = "") : name(name) {};
virtual ~Person() {}
string getInfo() { return name; }
};
class Student : public Person {
string studentid;
public:
Student(string name = "", string sid = "") : Person(name), studentid(sid) {};
string getInfo() { return name + ":(" + studentid + ")"; }
};
int main() {
Person person("Yu");
Student student("Sam", "20210212");
Person* pp = &student;
Person& rp = student;
Student* ps = (Student*)&person; // danger!
cout << "person.getInfo():" << person.getInfo() << endl;
cout << "pp->getInfo():" << pp->getInfo() << endl;
cout << "rp.getInfo():" << rp.getInfo() << endl;
cout << "ps->getInfo():" << ps->getInfo() << endl; // danger if getInfo is not virtual
char* p = (char*)100;
// ps = dynamic_cast<Student*>(&person);
// printf("address = %p\n", ps);
// pp = dynamic_cast<Person*>(&student);
// printf("address = %p\n", pp);
return 0;
}
dynamic_cast 只能用于含虚函数的类层次,转换失败时:
指针版本返回
nullptr;引用版本抛出
std::bad_cast异常。