RTII

运行时类型识别即RTTI主要由以下两个运算符实现

  • typeid,返回表达式类型
  • dynamic_cast,将基类指针或引用安全地转换成派生类指针或引用

运算符会自动使用指针或引用对象的动态类型。特别适用于想用基类指针或引用来执行派生类的不是虚函数的操作,即无法使用虚函数的情况。但实际上尽可能定义虚函数而非直接接管类型管理。
RTTI的实现主要是靠虚函数表之前的类型信息。

dynamic_cast

使用形式有

  • dynamic_cast<type*>(e)
  • dynamic_cast<type&>(e)
  • dynamic_cast<type&&>(e)

要求e的类型必须是type的公有派生类(向上转型)、公有基类(向下转型)或者type类型之一。如果e是指针,且转换失败,返回空指针;如果e是引用,且转换失败,抛出bad_cast异常。
指针类型:对于向下转型,如果e指向type对应的派生类,返回指向该派生类的指针;否则返回0。可以简单通过判断返回值是否为0来判断转换是否成功。
引用类型:对于向下转型,如果e引用的是type对应的派生类,返回指向该派生类的引用;否则抛出bad_cast异常。可以通过try-catch来判断转换是否成功。

typeid

可以用于任意类型的表达式,忽略顶层const,返回一个type_info对象,包含表达式的类型信息。
可以通过该函数比较两个表达式类型是否相同,注意应该作用于对象。
只有类型含有虚函数时,才会对表达式求值,否则直接返回表达式的静态类型,因为编译器知道。

一种使用情况

如何为具有继承关系的类实现相等运算符?通常来说相等意味着类型相同且成员取值相同。
如果定义一个虚函数,在继承体系的各个层次上分别实现,可以吗?不可以,因为虚函数的形参类型必须相同,而不同层次的参数类型不同,导致函数内只能比较共有成员。
因此可以使用RTTI,先使用typeid判断类型是否相同,如果相同再使用dynamic_cast转换成对应类型,再比较成员取值。

#include<iostream>
#include<typeinfo>
using namespace std;
class Base{
    friend bool operator==(const Base&, const Base&);
public:
    Base(int i = 0):a(i){}
private:
    int a;
protected:
    virtual bool equal(const Base& bs) const{
        return a == bs.a;
    }
};
class Derived: public Base{
public:
    Derived(int i = 0,int j = 0):Base(i),b(j){}
private:
    int b;
protected:
    bool equal(const Base& bs) const{
        const Derived* p = dynamic_cast<const Derived*>(&bs);
        return Base::equal(bs) && b == p->b;
    }
};
Base* getBase(Base* p ){
    cout << "in typeid" << endl;
    return p;
}
bool operator==(const Base& lhs, const Base& rhs){
    return typeid(lhs) == typeid(rhs) && lhs.equal(rhs);
}
class A{
};
A* getBase(A* p){
    cout << "in A*" << endl;
    return p;
}
int main()
{
    Base b1(1), b2(2);
    Derived d1(1, 2), d2(1, 2);
    A a;

    cout << typeid(*getBase(&b1)).name()<<endl;
    cout << typeid(*getBase(&a)).name()<<endl;

    cout << (b1 == b2) << endl;
    cout << (d1 == d2) << endl;
    cout << (b1 == d1) << endl;
    cout << (d1 == b1) << endl;
    return 0;
}
/*
in typeid
4Base
1A
0
1
0
0
*/

posted @ 2023-11-23 23:51  trashwin  阅读(25)  评论(0编辑  收藏  举报