• C++标准模板(STL)- 类型支持 (运行时类型识别,type_info )


    运行时类型识别

    定义于头文件

    含有某个类型的信息,由实现生成。​​这是 typeid 运算符所返回的类。

    std::type_info

    定义于头文件

    class type_info;

     类 type_info 保有一个类型的实现指定信息,包括类型的名称和比较二个类型相等的方法或相对顺序。这是 typeid 运算符所返回的类。

    type_info 既非可复制构造 (CopyConstructible) 亦非可复制赋值 (CopyAssignable) 。

    成员函数

    (构造函数)

    [被删除]

    无默认或复制构造函数
    (公开成员函数)

    (析构函数)

    [虚]

    通过指向基类的指针删除导出对象是安全的
    (虚公开成员函数)

    operator=

    [被删除]

    不能复制赋值
    (公开成员函数)

    operator==operator!=

    (C++20 中移除)

    检查对象是否指代相同类型
    (公开成员函数)

    before

    检查在实现定义的顺序中,被指代类型是否在另一个 type_info 对象之前,即对被指代类型排序
    (公开成员函数)

    hash_code

    (C++11)

    返回对于同一类型相同的值
    (公开成员函数)

    name

    类型的实现定义名称
    (公开成员函数)

     析构函数

    std::type_info::~type_info

    virtual ~type_info();

    析构 std::type_info 类型的对象。此析构函数为公开虚函数,允许通过指向基类的指针安全地删除从 std::type_info 导出的类的对象。

    检查对象是否指代相同类型

    1. std::type_info::operator==,
    2. std::type_info::operator!=

    bool operator==( const type_info& rhs ) const;

    (C++11 前)

    bool operator==( const type_info& rhs ) const noexcept;

    (C++11 起)

    bool operator!=( const type_info& rhs ) const;

    (C++11 前)

    bool operator!=( const type_info& rhs ) const noexcept;

    (C++11 起)
    (C++20 前)

     

    检查对象是否指代相同类型。

    参数
    rhs-要比较的另一个类型信息对象
    返回值

    若比较关系成立则为 true ,否则为 false

    调用示例
    1. #include <iostream>
    2. #include <typeinfo>
    3. #include <string>
    4. #include <utility>
    5. class person
    6. {
    7. public:
    8. person(std::string&& n) : _name(n) {}
    9. virtual const std::string& name() const
    10. {
    11. return _name;
    12. }
    13. private:
    14. std::string _name;
    15. };
    16. class employee : public person
    17. {
    18. public:
    19. employee(std::string&& n, std::string&& p) :
    20. person(std::move(n)), _profession(std::move(p)) {}
    21. const std::string& profession() const
    22. {
    23. return _profession;
    24. }
    25. private:
    26. std::string _profession;
    27. };
    28. void somefunc(const person& p)
    29. {
    30. if (typeid(employee) == typeid(p))
    31. {
    32. std::cout << p.name() << " is an employee ";
    33. auto& emp = dynamic_cast<const employee&>(p);
    34. std::cout << "who works in " << emp.profession() << std::endl;
    35. }
    36. }
    37. int main()
    38. {
    39. employee paul("Paul", "Economics");
    40. somefunc(paul);
    41. return 0;
    42. }
    输出

    检查在实现定义的顺序中,被指代类型是否在另一个 type_info 对象之前,即对被指代类型排序

    std::type_info::before

    bool before( const type_info& rhs ) const;

    (C++11 前)

    bool before( const type_info& rhs ) const noexcept;

    (C++11 起)

    若此 type_info 的类型在实现的对照顺序中列于 rhs 的类型之前则返回 true 。不给出保证,特别是对照顺序可以在同一程序的调用之间改变。

    参数
    rhs-要比较的另一个类型信息对象
    返回值

    若此 type_info 的类型在实现的对照顺序中列于 rhs 的类型之前则为 true 。

     调用示例
    1. #include <iostream>
    2. #include <typeinfo>
    3. int main()
    4. {
    5. if (typeid(int).before(typeid(char)))
    6. {
    7. std::cout << "int goes before char in this implementation.\n";
    8. }
    9. else
    10. {
    11. std::cout << "char goes before int in this implementation.\n";
    12. }
    13. return 0;
    14. }
    输出

    返回对于同一类型相同的值

    std::type_info::hash_code

    std::size_t hash_code() const noexcept;

    (C++11 起)

    返回未指定值,使得指代同一类型的所有 type_info 对象的 hash_code() 相同。

    不给出其他保证:指代不同类型的 type_info 对象可以拥有相同的 hash_code (尽管标准推荐实现尽可能避免这点),而同一类型的 hash_code 可在相同程序的各次不同调用间改变。

    参数

    (无)

    返回值

    对所有指代同一类型的 type_info 对象等同的值。

    调用示例
    1. #include <iostream>
    2. #include <typeinfo>
    3. #include <unordered_map>
    4. #include <string>
    5. #include <functional>
    6. #include <memory>
    7. struct A
    8. {
    9. virtual ~A() {}
    10. };
    11. struct B : A {};
    12. struct C : A {};
    13. using TypeInfoRef = std::reference_wrapper<const std::type_info>;
    14. struct Hasher
    15. {
    16. std::size_t operator()(TypeInfoRef code) const
    17. {
    18. return code.get().hash_code();
    19. }
    20. };
    21. struct EqualTo
    22. {
    23. bool operator()(TypeInfoRef lhs, TypeInfoRef rhs) const
    24. {
    25. return lhs.get() == rhs.get();
    26. }
    27. };
    28. int main()
    29. {
    30. std::unordered_map<TypeInfoRef, std::string, Hasher, EqualTo> type_names;
    31. type_names[typeid(int)] = "int";
    32. type_names[typeid(double)] = "double";
    33. type_names[typeid(A)] = "A";
    34. type_names[typeid(B)] = "B";
    35. type_names[typeid(C)] = "C";
    36. int i;
    37. double d;
    38. A a;
    39. // 注意我们存储指向 A 的指针
    40. std::unique_ptr<A> b(new B);
    41. std::unique_ptr<A> c(new C);
    42. std::cout << "i is " << type_names[typeid(i)] << std::endl;
    43. std::cout << "d is " << type_names[typeid(d)] << std::endl;
    44. std::cout << "a is " << type_names[typeid(a)] << std::endl;
    45. std::cout << "b is " << type_names[typeid(*b)] << std::endl;
    46. std::cout << "c is " << type_names[typeid(*c)] << std::endl;
    47. return 0;
    48. }
     输出

    类型的实现定义名称

    std::type_info::name

    const char* name() const;

    (C++11 前)

    const char* name() const noexcept;

    (C++11 起)

    返回实现定义的,含有类型名称的空终止字符串。不给出保证,尤其是返回的字符串对于数个类型可以相同,而且在同一程序的调用之间改变。

    参数

    (无)

    返回值

    含有类型名称的空终止字符串。

    注意

    返回指针所指向的数组的生存期未指定,但实践中只要给定类型的 RTTI 数据结构存在,它就得到保持,这拥有应用程序生存期,除非从动态库加载它(可被卸载)。

    一些实现(如 MSVC 、 IBM 、 Oracle )生成人类可读的类型名。其他的,最值得注意的是 gcc 与 clang ,返回重整名,这是由 Itanium C++ ABI 指定的。重整名可以用实现指定的 API 转换到人类可读的形式,例如直接用 abi::__cxa_demangle 或通过 boost::core::demangle 。它亦可通过命令行工具 c++filt -t 输送往管道。

     调用示例
    1. #include <iostream>
    2. #include <typeinfo>
    3. struct Base
    4. {
    5. virtual ~Base() = default;
    6. };
    7. struct Derived : Base {};
    8. int main()
    9. {
    10. Base b1;
    11. Derived d1;
    12. const Base *pb = &b1;
    13. std::cout << typeid(*pb).name() << std::endl;
    14. pb = &d1;
    15. std::cout << typeid(*pb).name() << std::endl;
    16. return 0;
    17. }
    输出

  • 相关阅读:
    Python在地球科学领域中的数据处理、科学计算、数学建模、数据挖掘和数据可视化
    操作系统知识点-处理机调度
    【LeetCode】错误的集合&&在排序数组中查找元素的第一个和最后一个位置&&杨氏矩阵&&寻找数组的中心下标&&两个数组的交集
    OpenFeign使用案例
    Python3,这应该是,配置文件最全的写法了。
    启动docker服务
    Linux shell编程学习笔记20:case ... esac、continue 和break语句
    从零开始实现lmax-Disruptor队列(四)多线程生产者MultiProducerSequencer原理解析
    loadrunner lr解决参数化一次取多条记录【一对多问题】
    烧录场景下的源代码防泄密方案分享
  • 原文地址:https://blog.csdn.net/qq_40788199/article/details/133976714