c++的四种强制类型转换为:static_cast dynamic_cast const_cast reinterpret_cast
c++相对于c的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换。
c++中风格是static_cast<type>(content)。它能更清楚的表明它们要干什么。
程序员也可以更直观的立即知道一个强制转换的目的。
static_cast:可以实现c++中内置基本数据类型之间相互转换。
int C = static_cast<int>(7.889);
如果涉及到类的话,static_cast只能在有相互联系的类型中进行相互转换,不一定包含虚函数。
const_cast:其操作不能在不同的种类间转换,相反,它仅仅能把它作用的表达式,转换常量。
它可以使一个本来不是const的类型转换成const类型,或者把const属性去掉。
reintepret_cast:(重新解释的计算)有着和C风格的强制转换同样的能力。他可以转化任何内置的数据类型为其他的任何数据类型,也可以转化任何指针类型为其他类型。他深灰可以转化内置的数据类型为指针,无需考虑类型安或常量的情形。不到万不得已绝对不用。
dynamic_cast:(动态的计算)
(1)其他三种都是编译时完成的,,而它是运行时处理的,运行时要进行类型检查。
(2)不能用于内置的基本数据类型的强制转换。
(3)转换如果成功的话返回的是指向类指针或引用,转换失败的话侧翻会NULL。
(4)使用dynamic_cast进行转化的基类中一定要有虚函数,否则编译不通过。
需要检测有虚函数的原因:类中存在虚函数类中存在虚函数,就说明它有想要让基类指针或引用指向子类对象的情况,此时转换才有意义。
(5)类的转换时:在类的层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的,在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
dynamic_cast主要用于“安全地向下转型(父类转换成子类)
这时本质上是:使用了一个父类指针指向子类对象,然后将这个指向子类对象的父类指针强制转换成子类指针。
Base * base = new Derived;
Derived* der = dynamic_cast<Derived*>(base);
怎么样?是不是很绕口?
dynamic_cast用于类继承层次间的指针或引用转换。主要还是用于执行“安全的向下转型(safe downcasting)”,也即是基类对象的指针或引用转换为同一继承层次的其他指针或引用。
至于“向上转型”(即派生类指针或引用类型转换为其基类类型),本身就是安全的,尽管可以使用dynamic_cast进行转换,但这是没必要的, 普通的转换已经可以达到目的,毕竟使用dynamic_cast是需要开销的。
class Base
{
public:
Base(){};
virtual void Show(){cout<<"This is Base calss";}
};
class Derived:public Base
{
public:
Derived(){};
void Show(){cout<<"This is Derived class";}
};
int main()
{
Base *base ;
Derived *der = new Derived;
//base = dynamic_cast<Base*>(der); //正确,但不必要。
base = der; //先上转换总是安全的
base->Show();
system("pause");
}
对于“向下转型”有两种情况。一种是基类指针所指对象是派生类类型的,这种转换是安全的;另一种是基类指针所指对象为基类类型,在这种情况下dynamic_cast在运行时做检查,转换失败,返回结果为0;
说明:有继承关系的情况下,子类向父类dynamic_cast转换(向上转型),是可行的,
但是父类向子类dynamic_cast转换(向下转型),会失败
#include "stdafx.h"
#include<iostream>
using namespace std;
class Base
{
public:
Base(){};
virtual void Show(){cout<<"This is Base calss";}
};
class Derived:public Base
{
public:
Derived(){};
void Show(){cout<<"This is Derived class";}
};
int main()
{
//这是第一种情况
Base* base = new Derived;
if(Derived *der= dynamic_cast<Derived*>(base))
{
cout<<"第一种情况转换成功"<<endl;
der->Show();
cout<<endl;
}
//这是第二种情况
Base * base1 = new Base;
if(Derived *der1 = dynamic_cast<Derived*>(base1))
{
cout<<"第二种情况转换成功"<<endl;
der1->Show();
}
else
{
cout<<"第二种情况转换失败"<<endl;
}
delete(base);
delete(base1);
system("pause");
}
在前面的例子中,使用了dynamic_cast将基类指针转换为派生类指针,也可以使用dynamic_cast将基类引用转换为派生类引用。
同样的,引用的向上转换总是安全的:
Derived c;
Derived & der2= c;
Base & base2= dynamic_cast<Base&>(der2);//向上转换,安全
base2.Show();
所以,在引用上,dynamic_cast依旧是常用于“安全的向下转型”。与指针一样,引用的向下转型也可以分为两种情况,与指针不同的是,并不存在空引用,所以引用的dynamic_cast检测失败时会抛出一个bad_cast异常:
int main()
{
//第一种情况,转换成功
Derived b ;
Base &base1= b;
Derived &der1 = dynamic_cast<Derived&>(base1);
cout<<"第一种情况:";
der1.Show();
cout<<endl;
//第二种情况
Base a ;
Base &base = a ;
cout<<"第二种情况:";
try{
Derived & der = dynamic_cast<Derived&>(base);
}
catch(bad_cast)
{
cout<<"转化失败,抛出bad_cast异常"<<endl;
}
system("pause");
}
- 使用dynamic_cast转换的Base类至少带有一个虚函数
当一个类中拥有至少一个虚函数的时候,编译器会为该类构建出一个虚函数表(virtual method table),虚函数表记录了虚函数的地址。如果该类派生了其他子类,且子类定义并实现了基类的虚函数,那么虚函数表会将该函数指向新的地址。虚表是C++多态实现的一个重要手段,也是dynamic_cast操作符转换能够进行的前提条件。当类没有虚函数表的时候(也即一个虚函数都没有定义),dynamic_cast无法使用RTTI,不能通过编译(个人猜想...有待验证)。
当然,虚函数表的建立对效率是有一定影响的,构建虚函数表、由表查询函数 都需要时间和空间上的消耗。所以,除了必须声明virtual(对于一个多态基类而言),不要轻易使用virtual函数。对于虚函数的进一步了解,可以查看《Effective C++》
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)