这些C++工程师面试题你都会了吗?——1.3说一说C++中四种 cast 转换

1、const_cast
用于将 const 变量转为非 const
const_cast 目前基本只用在 const 的转换上,基本无其他用法,比较单一

2、static_cast
用于各种隐式转换,比如非 const 转 const,void* 转指针等, static_cast 能用于多态向上转化,如果向下转能成功但是不安全,结果未知;

1)用于基本数据类型之间的转换,如把 int 转换为 char,把 int 转换成 enum,但这种转换的安全性需要开发者自己保证(这可以理解为保证数据的精度,即程序员能不能保证自己想要的程序安全),如在把 int 转换为 char 时,如果 char 没有足够的比特位来存放 int 的值(int > 127或 int <-127 时),那么 static_cast 所做的只是简单的截断,及简单地把 int 的低 8 位复制到 char的 8 位中,并直接抛弃高位。
(2)把空指针转换成目标类型的空指针
(3)把任何类型的表达式类型转换成 void 类型
(4)用于类层次结构中父类和子类之间指针和引用的转换。
对于以上第(4)点,存在两种形式的转换,即上行转换(子类到父类)和下行转换(父类到子类)。对于 static_cast,上行转换时安全的,而下行转换时不安全的,为什么呢?因为 static_cast 的转换是粗暴的,它仅根据类型转换语句中提供的信息(尖括号中的类型)来进行转换,这种转换方式对于上行转换,由于子类总是包含父类的所有数据成员和函数成员,因此从子类转换到父类的指针对象可以没有任何顾虑的访问其(指父类)的成员。而对于下行转换为什么不安全,是因为 static_cast 只是在编译时进行类型坚持,没有运行时的类型检查。

一般时候 static_cast 用的比较多,且与 const_cast 结合使用可以在父子类间完成常量属性与非常量属性的相关转换

3、dynamic_cast
用于动态类型转换。**只能用于含有虚函数的类,用于类层次间的向上和向下转化。只能转指针或引用。**向下转化时,如果是非法的对于指针返回NULL,对于引用抛异常。要深入了解内部转换的原理。

向上转换:指的是子类向基类的转换
向下转换:指的是基类向子类的转换

它通过判断在执行到该语句的时候变量的运行时类型和要转换的类型是否相同来判断是否能够进行向下转换。

class Widget
{
    public:
        virtual ~Widget(){};
};
 
class SpecialWidget:public Widget{};

void update(SpecialWidget *psw){};

int main()
{
    Widget *pw1=new SpecialWidget();//编译运行正常
    Widget *pw2=new Widget();//编译运行正常
    Widget *pw;  //编译正常,运行异常
    update(dynamic_cast<SpecialWidget*>(pw));
    return 0;
}
class Base1
{
    virtual void f(){}
};

class Base2{};

class Derived:public Base1,public Base2{};

int main(int argc, char* argv[])
{
    Derived d,*pd;
    Base1 *b1=&d;
 
    //用法一
    if((pd = dynamic_cast<Derived*>(b1)) != 0)
    {
        cout<<"pd结果指针类型为:"<<typeid(pd).name()<<endl;
    }
 
    //用法二 
    Base2 *b2;
    if((b2 = dynamic_cast<Base2*>(b1)) != 0)
    {
        cout<<"b2结果指针类型为:"<<typeid(b2).name()<<endl;
    }
}

结果如下:
pd结果指针类型为:P7Derived
b2结果指针类型为:P5Base2

4、reinterpret_cast
几乎什么都可以转,比如将 int 转指针,可能会出问题,尽量少用;
reinterpret_cast 的常用地方是转换”函数指针”类型。
如下:

typedef void (*FuncPtr)();        //定义一个无参数且无返回值的函数指针
FuncPtr funcPtrArray[10];         //定义一个长度为10的数组,数组元素是函数指针类型
int doSomething(){  return 1;};   //定义一个无参返回值为int的函数
int main()
{
//funcPtrArray[0]=&doSomething;  错误,函数类型不相符
funcPtrArray[0]=reinterpret_cast<FuncPtr>(&doSomething);  //函数名就是一个地址,因此取地址符是可选的

/*
但 reinterpret_cast与编译器平台相关,因此不具有移植性,使用范围也有限。 
另外,倘若你用过的编译器版本比较老,不支持上面这些新用法,其实还可以用宏定义来实现强制类型转换的功能。
*/

5、为什么不使用 C 的强制转换?
C的强制转换表面上看起来功能强大什么都能转,但是转化不够明确,不能进行错误检查,容易出错。

参考
《四种cast转换》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值