C++显式转换

static_cast

任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast(C++ Primer)。更为简单的解释就是,使用这个类型转换符,能够进行比较自然的转换,类别相近的转换,而有一些类型差距明显的转换则不可以,例如:

  1. 不能用于不同类型的指针之间转换(void * 除外);
  2. 不能用于整型与指针之间的转换;
  3. 不能用于不同类型的引用之间的转换。

示例如下:

    int n = 0, * ptr = &n, &ref = n;
    char ch = static_cast<char>(n);         // 正确
    void *vptr = static_cast<void*>(ptr);   // 正确 
    char *cptr = static_cast<char*>(ptr);   // 错误,指针类型不同且不是void*
    int *iptr = static_cast<int*>(n);       // 错误,整型不能转换为指针
    char &cref = static_cast<char&>(ref);   // 错误,引用类型不同

reinterpret_cast

reinterpret_cast通常为运算对象的位模式提供较低层次的重新解释,转换时,执行的是逐个比特复制的操作。常常用于进行各种不同类型的指针之间、不同类型的引用之间以及指针和能容纳指针的整数类型之间的转换,示例如下:

    int n = 0, * ptr = &n, &ref = n;
    char ch = reinterpret_cast<char>(n);         // 错误,reinterpret_cast不会对其进行截取
    void *vptr = reinterpret_cast<void*>(ptr);   // 正确 
    char *cptr = reinterpret_cast<char*>(ptr);   // 正确
    int *iptr = reinterpret_cast<int*>(n);       // 正确
    char &cref = reinterpret_cast<char&>(ref);   // 正确

可以看出,即使是两个不相关的类型之间也可以使用reinterpret_cast进行转换,但是在这其中很多转换的危险性是很大的,需要程序员来保证其安全。

const_cast

const_cast只能改变运算对象的底层const,将常量对象转换成为常量对象,这种行为也被称为“去掉const性质”。如果对象本身不是一个常量,使用强制类型转换获得写权限是合法的行为。而如果对象是一个常量,再使用const_cast执行写操作就会产生未定义后果。示例如下:

    const char *cptr;
    char *p = const_cast<char*>(cptr);        // 正确,但通过p写值是未定义的

dynamic_cast

dynamic_cast可以将基类的指针显式转换为派生类的指针,或将基类的引用显式转换为派生类的引用。但是它不是无条件转换,在转换前它会检查指针(或引用)所指向对象的实际类型是否与转换的目的类型兼容,如果兼容转换才会发生,才能得到派生类的指针(或引用)。使用形式如下:

    dynamic_cast<type*>(e);
    dynamic_cast<type&>(e);
    dynamic_cast<type&&>(e);

第一种形式中,e必须是一个有效指针;第二种形式中,e必须是一个左值;第三种形式中,e不能是左值。如果一条dynamic_cast语句的转换目标是指针类型且转换失败了,则结果为0;如果转换目标是引用类型并且失败了,则dynamic_cast运算符将抛出一个bad_cast异常。

需要注意的是,dynamic_cast的许多实现版本执行速度相当慢。例如许多的实现版本中会有比较类名称字符串的操作,如果是深层继承或多重继承成本更高,在要求效率的代码中应该要慎用这种转换。

posted @ 2020-03-11 11:21  southernEast  阅读(154)  评论(0编辑  收藏  举报