首页 > 代码库 > C++ Primer 学习笔记_102_特殊工具与技术 --运行时类型识别[续]

C++ Primer 学习笔记_102_特殊工具与技术 --运行时类型识别[续]

特殊工具与技术

--运行时类型识别[]

 

三.RTTI的使用

当比较两个派生类对象的时候,我们希望比较可能特定于派生类的数据成员.如果形参是基类引用,就只能比较基类中出现的成员,我们不能访问在派生类中但不在基类中出现的成员.

因此我们可以使用RTTI,在试图比较不同类型的对象时返回假(false)

我们将定义单个相等操作符。每个类定义一个虚函数 equal,该函数首先将操作数强制转换为正确的类型。如果转换成功,就进行真正的比较;如果转换失败,equal 操作就返回 false

 

1.类层次

class Base
{
    friend bool operator==(const Base &,const Base &);

public:
    // interface member for base

private:
    virtual bool equal(const Base &) const;
};

class Derived : public Base
{
    friend bool operator==(const Derived &,const Derived &);

public:
    // interface member for base

private:
    virtual bool equal(const Base &) const;
};


2.类型敏感的相等操作符

bool operator==(const Base &lhs,const Base &rhs)
{
    return typeid(lhs) == typeid(rhs) && lhs.equal(rhs);
}

 

3.虚函数equal

层次中的每个类都必须定义自己的equal版本.派生类中的equal函数将以相同的方式开始:将实参强制转换成为类本身的数据类型.

bool Derived::equal(const Base &rhs) const
{
    //必须将其转换成为指针类型,其原因请参考上一篇C++ Primer博客
    if (const Derived *dp = dynamic_cast<const Derived *>(&rhs))
    {
        // compare two Derived objects and return result
    }

    return false;
}

 

4.基类equal函数

bool Base::equal(const Base &rhs) const
{
    // compare two Base objects and return result
}

  使用形参之前不必强制转换,*this和形参都是Base对象,所以对形参类型也定义了该对象的所有操作.

 

.type_info

type_info支持的操作

t1 == t2

如果两个对象 t1 和 t2 类型相同,就返回 true;否则,返回false 

t1 != t2

t1 != t2  如果两个对象 t1 和 t2 类型不同,就返回 true;否则,返回false 

t.name()

t.name()  返回 风格字符串,这是类型名字的可显示版本。类型名字用系统相关的方法产生

t1.before(t2)

返回指出 t1 是否出现在 t2 之前的 bool 值。before 强制的次序与编译器有关

 

因为打算作基类使用,type_info 类也提供公用虚析构函数。如果编译器想要提供附加的类型信息,应该在 type_info 的派生类中进行。 

默认构造函数和复制构造函数以及赋值操作符都定义为 private,所以不能定义或复制 type_info 类型的对象。 程序中创建 type_info 对象的唯一方法是使用 typeid 操作符。 

name 函数为 type_info 对象所表示的类型的名字返回 风格字符串。给定类型所用的值取决于编译器,具体来说,无须与程序中使用的类型名字匹配。对 name 返回值的唯一保证是,它为每个类型返回唯一的字符串。虽然如此,仍可以使用 name 成员来显示 type_info 对象的名字:

    int iobj;

    cout << typeid(iobj).name() << endl;
    cout << typeid(8.16).name() << endl;
    cout << typeid(std::string).name() << endl;
    cout << typeid(Base).name() << endl;
    cout << typeid(Derived).name() << endl;


G++编译器显示:


:name返回的格式和值随编译器而变化.type_info类随编译器而变.一些编译器提供的附加的成员函数,那些函数提供关于程序中所用类型的附加信息.

//P653 习题18.20
class A {};
class B : public A {};
class C : public B {};

int main()
{
    A *pa = new C();
    cout << typeid(*pa).name() << endl; //1A
    cout << typeid(pa).name() << endl;  //P1A

    C cobj;
    A &ra = cobj;
    cout << typeid(&ra).name() << endl; //P1A
    cout << typeid(ra).name() << endl;  //1A

    B *px = new B;
    A &raTest = *px;
    cout << typeid(raTest).name() << endl;  //1A
}