C++四种常用的类型转换机制

时间:2022-12-09 22:12:25

    在C语言中,我们常常使用 (type)expression 这样的语句来把expression表达式强制转换为type类型的数据,而在c++中我们引用了四种类型转换操作符:const_cast,static_cast,dynamic_cast和reinterpret_cast;

1、static_cast 的威力和c语言的旧式转型有相同的效果和相同的限制;

2、dynamic_cast 将指向基类对象的指针或者引用转型为派生类(安全向下转型),并且在转型的过程中可以获知转型是否成功,对于指针,如果转型失败会返回一个null指针,如果是对引用转型失败,会抛出一个bad_cast异常,dynamic_cast通常情况下应该用于包含虚函数的类型上(因为dynamic_cast操作符属于运行时类型识别操作,所以我们需要虚函数表来记录类的继承关系,包括父类和派生类,只有在包含虚函数的情况下,编译器才会为对象维护一个虚函数表,所以应该必须包含一个虚函数的类型才能运用此操作符!);

    dynamic_cast  <type*> (e);   //指针转换

    dynamic_cast  <type&> (e);  //引用转换

上面的两个表达式必须符合以下三个条件中的任一个:e的类型是目标type的公有派生类、e的类型是目标type的公有基类或者e的类型就是目标type的类型。


3、reinterpret_cast 该强制转换操作符的转换结果几乎总是和编译平台相关,所以不具有移植性,其最常用于函数指针的转换,某些情况下这样的转型可能会导致不正确的结果,所以这种操作尽量别用。

4、const_cast  上面三种操作符都不能移除变量的const和 volatile的特性,只有该操作符能改变变量的这种特性;


可能出现的问题:

class A
{
public:
A(const int& i,const int& j)
:x(i),y(j)
{
}
void reset()
{
x += 10;
y += 20;
}
void print()
{
cout<<"The x of the class A: "<<x<<endl;
cout<<"The y of the class A: "<<y<<endl;
}
private:
int x;
int y;
};

class B : public A
{
public:
B(const int& i,const int& j,const int& k)
:A(i,j)
{
z = k;
}

void reset()
{
static_cast<A>(*this).reset(); //<strong>执行类型转换,然后重新设置参数,产生一个临时的对象,*this对象并没有变化</strong>
//A::reset(); //得到结果与上面一行代码得到的结果不一样!!!
<span style="font-size:14px;">//<span style="font-size:14px;">static_cast<A*>(this).reset()</span></span>; //得到正确的结果
z += 1;
}

void print()
{
A::print();
cout<<"The z of this B class is: "<<z<<endl;
}
private:
int z;
};
int main()
{
B b(20,30,2);
b.reset();
b.print();
}

上面的可能出现问题的地方我已经用粗体标记出来了,所以当我们用到了类型强制转化的时候应该时刻警惕可能出现错误,导致程序得到一个“莫名其妙”的值:使用static_cast<A>(*this).reset(); 得到的结果为:
C++四种常用的类型转换机制

通过输出我们可以发现,明明调用了reset()函数,却发现x,y的值并没有改变,只是z的值变化了;

当我们使用A::reset();函数时得到的结果如下:

C++四种常用的类型转换机制

可以发现x,y,z的值都变化了,因为当我们用强制转换的时候得到了(*this)对象的副本,改变的也是副本的值,所以最终打印*this对象的数据成员时并没有reset x,y的值,所以得到上述结果。

当我把static_cast<A>(*this).reset()改为static_cast<A*>(this).reset();后通过指针的操作就可以得到正确的值,如下:

C++四种常用的类型转换机制

这进一步验证了改变的是*this对象副本的理论。