RTTI
Run-Time Type Identification 运行时类型识别,它使程序能够获取由基指针或引用所指向的对象的实际派生类型,即允许“用指向基类的指针或引用来操作对象”的程序能够获取到“这些指针或引用所指对象”的实际派生类型。
在C++中,为了支持RTTI提供了两个操作符:dynamic_cast和typeid
- dynamic_cast允许运行时刻进行类型转换,从而使程序能够在一个类层次结构中安全地转化类型,与之相对应的还有一个非安全的转换操作符static_cast,因为这不是本文的讨论重点,所以这里不再详述,感兴趣的可以自行查阅资料。
- typeid是C++的关键字之一,等同于sizeof这类的操作符。typeid操作符的返回结果是名为type_info的标准库类型的对象的引用。运行时获知变量类型名称,可以使用 typeid(变量).name()
#include <iostream>
#include <typeinfo>
using namespace std;
class White{};
class Black{};
int main()
{
White a;
Black b;
cout << typeid(a).name() << endl;
cout << typeid(b).name() << endl;
White c;
bool abSametype = (typeid(a).hash_code() == typeid(b).hash_code());
bool acSametype = (typeid(a).hash_code() == typeid(c).hash_code());
cout << "Same type?" << endl;
cout << "A and B ? " << abSametype << endl;
cout << "A and C ? " << acSametype << endl;
int i;
decltype(i) j = 0;
cout << typeid(j).name() << endl;
float f;
double d;
decltype(f + d) e;
cout << typeid(e).name() << endl;
}
decltype
decltype 是一个关键字,和auto的功能一样,用来在编译时期从一个表达式中推导出其类型。它通常与表达式一起使用,以便在编译时确定表达式的类型。.decltype
还可以用于推导函数返回类型,以及在泛型编程中处理模板的类型。
int x = 5;
decltype(x) y = 10; // y 的类型将被推导为 int
declval
declval是一个函数模板,用于在不实际调用构造函数的情况下生成一个对象引用,以便在类型推导中使用。通常在需要引用某个类型的对象但实际无法创建该对象的上下文中使用。
template <typename T>
auto createAndProcess() -> decltype(std::declval<T>().process()) {
// 此处只是用于类型推导,并不会实际创建 T 的对象
}
在这个例子中,std::declval<T>().process()
用于推导函数的返回类型,但并不会实际调用 process
函数。
std::decay
std::decay用于
移除类型中的一些特性,比如引用、常量、volatile,但是注意不包括指针特性,
class myclass{};
std::decay<const myclass &>::type var1;
// 变量var1的类型是myclass
std::decay_t
std::decay_t
是一个类型转换工具模板,用于将给定类型的"衰变"后的类型返回。衰变指的是将类型转换为其"自然"形式,即去掉引用、添加 cv 限定符(const 和 volatile)。
template< class T >
using decay_t = typename decay<T>::type;
using T1 = std::decay_t<int&>; // T1 为 int
using T2 = std::decay_t<const int>; // T2 为 int
using T3 = std::decay_t<int[]>; // T3 为 int*
总结
- typeid 是操作符,运行时返回表达式的动态类型
decltype
是关键字,用于有了值或对象求类型的std::declval
是函数模板,用于伪造一个对象但不实际构造的std::decay
是类模板,用于去除修饰符std::decay_t
是类模板,用于去除修饰符获取原始类型的