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

运行时类型识别

|---|---|
| 定义于头文件 <typeinfo> ||

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

复制代码
std::type_info

|---------------------|---|---|
| 定义于头文件 <typeinfo> | | |
| 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 导出的类的对象。

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

复制代码
std::type_info::operator==, 
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

调用示例
复制代码
#include <iostream>
#include <typeinfo>
#include <string>
#include <utility>

class person
{
public:

    person(std::string&& n) : _name(n) {}
    virtual const std::string& name() const
    {
        return _name;
    }

private:

    std::string _name;
};

class employee : public person
{
public:

    employee(std::string&& n, std::string&& p) :
        person(std::move(n)), _profession(std::move(p)) {}

    const std::string& profession() const
    {
        return _profession;
    }

private:

    std::string _profession;
};

void somefunc(const person& p)
{
    if (typeid(employee) == typeid(p))
    {
        std::cout << p.name() << " is an employee ";
        auto& emp = dynamic_cast<const employee&>(p);
        std::cout << "who works in " << emp.profession() << std::endl;
    }
}

int main()
{
    employee paul("Paul", "Economics");
    somefunc(paul);
    return 0;
}
输出

检查在实现定义的顺序中,被指代类型是否在另一个 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 。

调用示例
复制代码
#include <iostream>
#include <typeinfo>

int main()
{
    if (typeid(int).before(typeid(char)))
    {
        std::cout << "int goes before char in this implementation.\n";
    }
    else
    {
        std::cout << "char goes before int in this implementation.\n";
    }

    return 0;
}
输出

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

复制代码
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 对象等同的值。

调用示例
复制代码
#include <iostream>
#include <typeinfo>
#include <unordered_map>
#include <string>
#include <functional>
#include <memory>

struct A
{
    virtual ~A() {}
};

struct B : A {};
struct C : A {};

using TypeInfoRef = std::reference_wrapper<const std::type_info>;

struct Hasher
{
    std::size_t operator()(TypeInfoRef code) const
    {
        return code.get().hash_code();
    }
};

struct EqualTo
{
    bool operator()(TypeInfoRef lhs, TypeInfoRef rhs) const
    {
        return lhs.get() == rhs.get();
    }
};

int main()
{
    std::unordered_map<TypeInfoRef, std::string, Hasher, EqualTo> type_names;

    type_names[typeid(int)] = "int";
    type_names[typeid(double)] = "double";
    type_names[typeid(A)] = "A";
    type_names[typeid(B)] = "B";
    type_names[typeid(C)] = "C";

    int i;
    double d;
    A a;

    // 注意我们存储指向 A 的指针
    std::unique_ptr<A> b(new B);
    std::unique_ptr<A> c(new C);

    std::cout << "i is " << type_names[typeid(i)] << std::endl;
    std::cout << "d is " << type_names[typeid(d)] << std::endl;
    std::cout << "a is " << type_names[typeid(a)] << std::endl;
    std::cout << "b is " << type_names[typeid(*b)] << std::endl;
    std::cout << "c is " << type_names[typeid(*c)] << std::endl;

    return 0;
}
输出

类型的实现定义名称

复制代码
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 输送往管道。

调用示例
复制代码
#include <iostream>
#include <typeinfo>

struct Base
{
    virtual ~Base() = default;
};
struct Derived : Base {};

int main()
{
    Base b1;
    Derived d1;

    const Base *pb = &b1;
    std::cout << typeid(*pb).name() << std::endl;
    pb = &d1;
    std::cout << typeid(*pb).name() << std::endl;

    return 0;
}
输出
相关推荐
玖玥拾4 小时前
C/C++ 基础笔记(十四)多态与模板编程
c语言·c++·多态·模板
Roann_seo%5 小时前
C++文件操作完全指南:从文本读写到二进制文件处理
开发语言·c++
坚果派·白晓明6 小时前
【鸿蒙PC】SDL3 适配:AtomCode + Skills 快速集成 NAPI 测试工具
c++·华为·ai编程·harmonyos·atomcode
凡人叶枫6 小时前
Effective C++ 条款17:以独立语句将 newed 对象置入智能指针
java·linux·开发语言·c++·算法
凡人叶枫8 小时前
Effective C++ 条款16:成对使用 new 和 delete 时要采取相同形式
开发语言·c++·effective c++
不吃土豆的马铃薯8 小时前
C++ 高性能网络缓冲区 Buffer 源码解析
linux·服务器·开发语言·网络·c++
.千余8 小时前
【C++】C++继承入门(下):友元、静态成员与菱形继承的底层逻辑
开发语言·c++·笔记·学习·其他
初中就开始混世的大魔王9 小时前
6 Fast DDS-传输层
开发语言·c++·中间件·信息与通信
代码中介商11 小时前
C++ 智能指针完全指南(三):weak_ptr 与循环引用
开发语言·c++
BestOrNothing_201511 小时前
ROS2 C++ 小车控制完整实战(二):自定义 msg 消息发布与订阅保姆级教程
c++·ros2·subscriber·publisher·msg·topic通信·自定义接口