guodongxiaren/Blog

C++转型对比

Opened this issue · 0 comments

从C时代开始。转型主要分为两种:

  • 显式类型转换
  • 隐式类型转换

显示类型转换

显式类型转换C

极度不安全。对于不相关类型(非继承)的指针也可以转换……(其实反过来也可以利用)

static_cast<>c++

比C风格转型,安全性上高一些。可以识别出不相关类型指针的转换。在编译期间报错。
比如(clang):

error: static_cast from 'A *' to 'B *', which are not related by inheritance, is not allowed

dynamic_cast<>c++

要点:

  • 原类型含有虚函数
  • 模板类型要是指针或者引用

错误1:转换成非指针/引用类型

B b = dynamic_cast<B>(a);

error: 'B' is not a reference or pointer

错误2:给不带虚函数的类型指针转换

用dynamic_cast给不带虚函数的类型指针转换。报错:

A *pa = new A;
A a;
B* pb = dynamic_cast<B*>(pa);
B b = dynamic_cast<B&>(a);

上面两次转换都报错:

error: 'A' is not polymorphic

给类A加上一个virtual的函数。再抓成不相关的类型B。
不报错。

正确用法

class A {
public:
    virtual void echo() {
        cout<<"A"<<endl;
    }
};
class B {
public:
    void echo() {
        cout<<"B"<<endl;
    }
};
int main() {
    A *a = new A;
    B* b = dynamic_cast<B*>(a);
    b->echo(); // 输出 B
    return 0;
}

指针下行转换(能编译通过)

父类指针转换为子类指针,编译不失败。两种情况:

  • 父类指针指向的实际是子类对象。成功转型。
  • 父类指针指向的就是父类对象。编译无异常,只是返回值是NULL。

dynamic_cast无二义性。不会一个编译通过,一个不通过。而实际转型成功与否交给实际情况去判断。这个其实就是RTTI

reinterpret_cast <>c++

最不安全的类型转换。像C转换一样,两个指针可以毫不相干。
另外它也要求转换目标类型为指针或者引用。

const_cast<>c++

消除const属性!一般工作中被禁止使用。

总结

上行转换,通常安全。下行转换很可能不安全。
static_cast效率比dynamic_cast高。因为RTTI效率更低。
但static_cast可能不够安全!
个人总结,只有父类有虚函数,就用dynamic_cast。没有就用static_cast。


Reference