C++与类型转换相关的关键字

C++一共有四种与类型转换相关的关键字,分别为:

(1): static_cast,
(2): dynamic_cast,
(3): const_cast
(4): reinterpret_cast
它们的代码格式统一为:
cast-name < type > (expression);
其中cast-name是转换方式关键字,type是转换的目标类型,expression是被转换的值

1. static_cast

任何编写程序时能够明确的类型转换都可以使用static_cast(static_cast不能转换掉底层的const,volatile和__unaligned属性)。由于不提供运行时的检查,所以叫static_cast,因此,需要在编写程序时确认转换的安全性。
主要在以下几种场合中使用:
1. 用于类层次结构中,父类和子类之间指针和引用的转换;进行上行转换,把子类对象的指针/引用转换为父类的指针/引用,这种转换是安全的;进行下行转换,把父类对象的指针/引用转换成子类的指针/引用,这种转换是不安全的,需要编写程序时来确认;
2. 用于基本数据类型之间的转换,例如把int转换成char,int转换成enum等,需要编写程序时来确认安全性。
3. 把void指针转换成目标类型的指针(这是极不安全的);
示例:

int i, j;
double slope = static_cast<double>(j) / i;
void *p = &slope;
double *dp = static_cast<double*>(p);

2. dynamic_cast

相比static_cast,dynamic_cast会在运行时检查类型转换是否合法,具有一定的安全性。由于运行时的检查,所以会额外消耗一些性能。dynamic_cast使用场景与static相似,在类层次结构中使用时,上行转换和static_cast没有区别,都是安全的;下行转换时,dynamic_cast会检查转换类型,相比static_cast更安全。
dynamic_cast转换仅适用于指针或引用
在转换可能发生的前提下,dynamic_cast会尝试转换,若指针转换失败,则返回空指针,若引用转换失败,则抛出异常。
1. 继承中的转换
(1)上行转换
在继承关系中,dynamic_cast由子类向父类的转换与static_cast和隐式转换一样,都是非常安全的。
(2)下行转换

class A{virtual void f(){};};
class B:public A{};
void main()
{
    A *pA = new B;
    B *pB = dynamic_cast(pA);
}

注意类A和类B中定义了一个虚函数,这是不可缺少的。因为类中存在虚函数,说明它可能有子类,这样才有类型转换的情况发生,由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表中,只有定义了虚函数的类才有虚函数表。
2. void *的转换
一些情况下,我们需要将指针转换为void*,然后在合适的时候重新将void*转换为目标类型指针。

class A{virtual void f(){}};
int main()
{
    A *pA = new A;
    void *pV = dynamic_cast<void*>(pA);
}

3 菱形继承中的上行转换
首先,定义一组菱形继承的类:

class A{virtual void f(){};};
class B:public A{void f(){};};
class C:public A{void f(){};};
class D:public B, public C{void f(){};};

继承关系如图
B继承A,C继承A,D继承B和C。
考虑这样的情况:D对象指针能否安全转换为A类型指针?
直觉来看是可以的,因为从子类向父类转换总是安全的。

class A{virtual void f(){};};
class B:public A{void f(){};};
class C:public A{void f(){};};
class D:public B, public C{void f(){};};

void main()
{
    D *pD = new D;
    A *pA = dynamic_cast(pD); // pA = NULL
}

但实际上,如果尝试这样的转换,只能得到一个空指针。因为B和C都继承了A,并且都实现了虚函数f(),导致在转换时,无法选择一条转换路径。
一种可行的方法时,自行指定一条转换路径:

void main()
{
    D *pD = new D;
    B *pB = dynamic_cast(pD);
    A *pA = dynamic_cast(pB);
}

3. const_cast

const_cast用于移除类型的const、volatile和__unaligned属性。
常量指针被转换成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象。

const char *pc;
char *p = const_cast<char*>(pc);

4. reinterpret_cast

非常激进的指针类型转换,在编译期完成,可以转换任何类型的指针,所以极不安全。非极端情况不要使用。

int *ip;
char *pc = reinterpret_cast<char*>(ip);

你可能感兴趣的:(C/C++程序设计)