RTTI
来源:互联网 发布:cpa软件 编辑:程序博客网 时间:2024/05/01 21:17
通过RTTI,能够通过基类的指针或引用来检索其所指对象的实际类型。c++通过下面两个操作符提供RTTI。
(1)typeid:返回指针或引用所指对象的实际类型。
(2)dynamic_cast:将基类类型的指针或引用安全的转换为派生类型的指针或引用。
对于带虚函数的类,在运行时执行RTTI操作符,返回动态类型信息;对于其他类型,在编译时执行RTTI,返回静态类型信息。
当具有基类的指针或引用,但需要执行派生类操作时,需要动态的强制类型转换(dynamic_cast)。这种机制的使用容易出错,最好以虚函数机制代替之。
dynamic_cast 操作符
如果dynamic_cast转换指针类型失败,则返回0;如果转换引用类型失败,则抛出一个bad_cast类型的异常。
可以对值为0的指针使用dynamic_cast,结果为0。
dynamic_cast会首先验证转换是否有效,只有转换有效,操作符才进行实际的转换。
if (Derived *derivedPtr = dynamic_cast<Derived *>(basePtr)){ // use the Derived object to which derivedPtr points}else{ // basePtr points at a Base object // use the Base object to which basePtr points}
也可以使用dynamic_cast将基类引用转换为派生类引用:dynamic_cast<Type&>(val)
因为不存在空引用,所以不能像指针一样对转换结果进行判断。不过转换引用类型失败时,会抛出std::bad_cast异常。
try{ const Derived &d = dynamic_cast<const Derived&>(b);}catch (bad_cast) { // handle the fact that the cast failed.}
typeid操作符
typeid能够获取一个表达式的类型:typeid(e)。
如果操作数不是类类型或者是没有虚函数的类,则获取其静态类型;如果操作数是定义了虚函数的类类型,则计算运行时类型。
typeid最常见的用途是比较两个表达式的类型,或者将表达式的类型与特定类型相比较。
Base *bp;Derived *dp;// compare type at run time of two objectsif (typeid(*bp) == typeid(*dp)){ // bp and dp point to objects of the same type}// test whether run time type is a specific typeif (typeid(*bp) == typeid(Derived)){ // bp actually points a Derived}
注意:如果是typeid(bp),则是对指针进行测试,这会返回指针(bp)的静态编译时类型(Base *)。
如果指针p的值是0,,并且指针所指的类型是带虚函数的类型,则typeid(*p)抛出一个bad_typeid异常。
RTTI的使用
如果有一个类层次,希望为它实现“==”操作符。假设类层次中只有2个类型,那么需要4个函数:
bool operator==(const Base&, const Base&)bool operator==(const Derived&, const Derived &)bool operator==(const Derived &, const Base&)bool operator==(const Base&, const Derived &)
如果类层次中有4个类型,就要实现16个操作符函数,这种实现就太麻烦了。下面来看如何使用RTTI解决这个问题。
只定义1个“==”操作符函数,每个类定义一个虚函数equal。
class Base{ friend bool operator==(const Base&, const Base&);public: // interface members for Baseprotected: virtual bool equal(const Base&) const; // data and other implementation members of Base};bool Base::equal(const Base &rhs) const{ // do whatever is required to compare to Base objects}class Derived: public Base{ friend bool operator==(const Base&, const Base&);public: // other interface members for Derivedprivate: bool equal(const Base&) const; // data and other implementation members of Derived};bool Derived::equal(const Base &rhs) const{ if (const Derived *dp = dynamic_cast<const Derived *>(&rhs)) { // do work to compare two Derived objects and return result } else return false;}bool operator==(const Base &lhs, const Base &rhs){ // returns false if typeids are different otherwise // returns lhs.equal(rhs) return typeid(lhs) == typeid(rhs) && lhs.equal(rhs);}
如果操作数类型不同,操作符就返回假;如果操作数类型相同,就将实际比较操作数的工作委派给适当的虚函数equal。
Derived::equal()中的dynamic_cast强制转换是必要的。因为要比较派生类的成员,必须将操作数Base &转换为Derived类型。
type_info类
type_info类的实现因编译器的不同而不同。但如下几个常用的操作符和函数是c++标准要求必须实现的:“t1 == t2”、“t1 != t2”、“t.name()”。
typeid操作符的返回类型就是type_info,正因为type_info提供了“==”操作符,才可以进行上面提到的“if (typeid(*bp) == typeid(*dp))”判断。
type_info的默认构造函数、拷贝构造函数、赋值操作符都定义为private,创建type_info对象的唯一方法就是使用typeid操作符。
name()函数返回类型名字的c-style字符串,但字符串的格式可能不同的编译器略有不同。下面是在vc2008编译器下的测试。
// expre_typeid_Operator.cpp// compile with: /GR /EHsc#include <iostream>#include <typeinfo.h>class Base {public: virtual void vvfunc() {}};class Derived : public Base {};using namespace std;int main() { Derived* pd = new Derived; Base* pb = pd; int i = 0; cout << typeid( i ).name() << endl; // prints "int" cout << typeid( 3.14 ).name() << endl; // prints "double" cout << typeid( pb ).name() << endl; // prints "class Base *" cout << typeid( *pb ).name() << endl; // prints "class Derived" cout << typeid( pd ).name() << endl; // prints "class Derived *" cout << typeid( *pd ).name() << endl; // prints "class Derived" delete pd;}
- RTTI
- RTTI
- rtti
- RTTI
- RTTI
- RTTI
- RTTI
- RTTI
- RTTI
- RTTI
- RTTI
- RTTI
- RTTI
- RTTI
- RTTI
- RTTI
- RTTI
- RTTI
- 在Ubuntu上下载、编译和安装Android最新内核源代码(Linux Kernel)
- 【HTTP】Fiddler(三)- Fiddler命令行和HTTP断点调试
- jquery获取元素值的方法(常见的表单元素)
- 使用afnetworking和网络服务接口及soap发送并接收http/https请求:
- 我不是《纪念碑谷》,我是玩法不一样的《Maestria》
- RTTI
- struts拦截器原理
- OpenCV Stitching 工程搭建
- 如何单独编译Android源代码中的模块
- 进程里杀死tomcat
- 一致性哈希算法学习笔记
- ie8的透明度&&透明度的兼容性写法
- 哥伦比亚大学Coursera课程Natural Language Processing:Quiz 1: covers material from weeks 1 and 2
- Ubuntu14.04 GLUT的安装