zhouqijie

静态类型信息判断

有时要在模板中根据不同的类型做出不同的处理,可以使用静态类型信息判断。



示例

判断类型参数T是否是双精度浮点数:

template<typename T> struct IsDouble{enum{value = false};}//默认情况
template<> struct IsDouble<double>{enum{value = true};}//T为double时候返回true  



STL中的接口

std::is_integral<int>().value;
std::is_floating_point<int>().value;





运行时类型识别(RTTI)

CRE:RTTI的用途是得知指针指向的是什么类型的对象。
Cheng:一般编译器不建议开启这个选项,因为RTTI有一定的性能损耗。

RTTI工作原理

C++有3个支持RTTI的元素:

  1. dynamic_cast运算符将使用一个指向基类的指针来生成一个指向子类的指针,否则返回0,即空指针。
  2. typeid运算符返回一个指出对象的类型的值。
  3. type_info结构存储了有关特定类型的信息。

C++ RTTI只适合包含虚函数的类。

dynamic_cast运算符

dynamic_cast运算符能得出是否可以安全地将对象地址赋给特定类型的指针

格式:Person * p = dynamic_cast<Student *>(s);
如果转换成功,返回对象地址。否则返回空指针。

typeidtype_info

typeid运算符能使得能够确定两个对象是否是同种类型
typeid用法和sizeof相似,接收类名或者对象作为参数。

typeid返回一个对type_info对象的引用,type_info是在头文件typeinfo中定义的一个类。
type_info重载了==!=运算符以便对类型进行比较。
type_info的实现随厂商而异,但都包含一个name()成员,该函数返回一个随实现而异的字符串,通常是类名。





类型转换运算符

C++的类型转换相比C语言的类型转换更加严格更规范。

  1. dynamic_cast
  2. const_cast
  3. static_cast
  4. reinterpret_cast

const_cast运算符

用于只有一种用途的类型转换,即改变值为constvolatile特征。

提供该运算符的原因是,有时候可能需要这样一个值,它在大多数时候是常量,而有时又是可以修改的。这种情况下,可以将这个值声明为const,并在需要修改它的时候使用const_cast
这也可以通过通用类型转换(T*)来实现,但是为了避免同时改变类型和常量特征,所以使用const_cast更安全。

static_cast运算符

格式:static_cast<T>(exp)

只有当T类型可以隐式转换为exp所属类型或者exp可被转换为T所属类型时,上述转换才算合法。(即支持upcast和downcast)
即可从基类转换为子类,或从子类转换为基类。但是不能转换为无关的类。

由于无需类型转换,枚举值就可以被转换为整型,所以可以用static_cast将整型转换为枚举值。

可以使用static_castdouble转化为int、将float转换为long以及其他各种数值转换。

reinterpret_cast运算符

用于天生危险的类型转换。它不允许删除const,但会执行其他令人生厌的操作。

CRE:reinterpret_cast即重新解释指针。

struct data{ short a; short b;}
long value = 0xA224B118;
data * p = reinterpret_cast<data *> (&value);





RTTI的其他实现方式

类的Static类型字段

class Type
{
    //...
}
class A
{
    static Type type;
    virtual Type * GetType const { return type; }
    //...
};
//每个类都要定义。可以封装成宏方便调用。    

虚函数

class A
{
public:
    enum TYPE
    {
        T_A,
        T_B,
    }
    virtual TYPE GetType(){ return T_A; }
}
class B : public A
{
public:
    virtual TYPE GetType(){ return T_B; }
}

(END)