• C++特殊工具与技术之RTTI


    类型识别分为两种:一种以编译时类型识别,一种是运行时类型识别

    编译时类型识别:static_cast;

    运行时类型识别(RTTI),C++通过下面连个操作符提供RTTi;

    1)dynamic_cast操作符,将基类类型的指针或者引用安全地转换为派生类型的指针或者引用;

    2)typeid操作符,返回指针或者引用所指对象的实际类型。

    注意:若想要实现运行时类型识别,则要求其使用类型为 至少带有一个虚函数的类。对于其他类型,返回静态(即编译时)类型的信息。


    为叙述方便,我们先把所用的类的代码写出,其中Animal为基类,Cat、Dog类为其派生类;

     1 class Animal
     2 {
     3     public:
     4         virtual ~Animal(){ }
     5         virtual void run()
     6         { cout<< "test" << endl; }
     7 };
     8 
     9 class Cat:public Animal
    10 {
    11     public:
    12         void run()
    13         { cout << "Cat..." << endl;  }
    14 };
    15 
    16 class Dog:public Animal
    17 {
    18     public:
    19         void run()
    20         {  cout << "Dog.." << endl; } 
    21 };

    一、static_cast(静态类型转换)的示例代码如下:

     1 //static_cast发生在编译期间
     2 #include <iostream>
     3 #include <string>
     4 #include <vector>
     5 using namespace std;
     6 
     7 int main(int argc, const char *argv[])
     8 {
     9     Animal *base;
    10     Cat c;
    11     Dog d;
    12     base = &c;
    13 
    14     Cat *pc = static_cast<Cat*>(base);
    15     pc->run();//Cat... 
    16 
    17     Dog *pd = static_cast<Dog*>(base);
    18     pd->run();//Cat..打印的是实际指向的Cat对象
    19     return 0;
    20 }
    注意:static_cast发生在编译期间,如果转化失败,那么会产生编译错误;若果编译成功,那么则转化成功。但是static_cast仍具有一定风险,尤其是向下塑形时。将Base*(基类指针)转化为Deriverd*(派生类指针)时,指针可以转化,但是指针未必指向Derived对象。


    二、dynamic_cast(动态运行转换)示例代码如下:

    转换引用:

    //转换引用
    int main(int argc, const char *argv[])
    {
        Cat c;
        Dog d;
        Animal &base = c;//引用时必须初始化
    
        Cat &pc = dynamic_cast<Cat&>(base);
        cout << &pc << endl; 
        //test_result 0xbfebb0
        Dog &pd = dynamic_cast<Dog&>(base);
        cout << &pd << endl;
        //test_result  bad_cast 与指针不同
        return 0;
    }


    转换指针:

    //转换指针
    int
    main(int argc, const char *argv[]) { Cat c; Dog d; Animal *base = &c; Cat *pc = dynamic_cast<Cat*>(base); cout << pc << endl; //打印指针的地址 //test_result oxbf94b98c Dog *pd = dynamic_cast<Dog*>(base); cout << pd << endl; //test_result 0 //转化未成功 return 0; }
    注意:与dynamic_cast一起使用的指针必须是有效的--它必须为NULL,或者指向一个对象

    dynamic_cast的具体实现:
    1、dynamic_cast涉及运行时类型检查。如果绑定到引用或者指针的对象不是目标类型的对象 ,则dynamic_cast失败;

    a)若是转换到指针类型 的dynamic_cast失败, 则dynamic_cast的结果为 0

    b)若是转换到引用类型 的dynamic_cast失败, 则抛出一个 bad_cast类型的异常

    步骤:dynamic_cast操作符一次执行两次操作;
    1:首先验证被请求的转换是否有效;
    2、在转换有效的情况下,操作符才实际进行转换。

    C++primer 4th给出了使用dynamic_cast操作符的标准实践

    //指针情况、
    if(Derived *derivedPtr = dynamic_cast<Derived*>(basePtr)
    {
        //转化成功
    }
    else
    {
        //失败处理
    }

    引用情况:

    //引用情况
    try
        {
            const Derived &d = dynamic_cast<const Derived&>(b);
            //成功情况
        }
        catch(bad_cast)
        {
            //失败处理
        }

    这段代码的逻辑是非常严密的:

    Derived *derivedPtr 的作用域只存在于if语句中
    不可能在dynamic_cast和测试转换结果之间插入代码,因此不可能在测试转换成功之前使用derivedPtr。


    三、typeid运行时类型转换;

    typeid的作用机制和dynamic_cast类似。示例代码如下:

     1 int main(int argc, const char *argv[])
     2 {
     3     Cat c;
     4     Dog d;
     5     cout << typeid(string).name() << endl;
     6     //类型名 
     7     cout << typeid(c).name() << endl;//3Cat
     8     cout << typeid(d).name() << endl;//3Dog
     9     Animal a;
    10     cout << typeid(a).name() << endl;//6Animal
    11     Animal *pa = &c;
    12     cout << typeid(*pa).name() << endl;//3Cat
    13 
    14     return 0;
    15 }
    只有当typeid的操作数满足以下两个条件时,才返回动态类型信息,
    a)带有虚函数;
    b)是类类型的对象。
    另外,测试指针(相对于指针指向的对象)返回指针的静态的、编译时的类型。

     RTTI的实例:C++ RTTI的使用

  • 相关阅读:
    Python安装的库列表导出到文件和批量安装库文件
    Selenium之浏览器驱动下载和配置使用
    测试面试计算题--python
    软件质量模型
    用例要素和设计方法
    python的层级
    day 14:深浅copy,数据结构 ,函数,set集合,变量作用域、返回值
    day 8:open文件和with的使用
    day 1:计算机发展史和组成部分
    day 2:计算机的基础知识,编程语言分类
  • 原文地址:https://www.cnblogs.com/xfxu/p/4012368.html
Copyright © 2020-2023  润新知