C++的类型转换(Type Casting)

C++的类型转换包括了两类,隐式转换和显式转换。


隐式转换常见于两种情况,一种是基础类型运算时,自动从低精度类型向高精度类型转换,如char转int、int转double等。

int a = 100;
double b = a / 4.0;

另一种情况是对象之间赋值,隐式地调用了复制构造函数。

class A { };
class B { public: B(A a) { } };

A a;
B b = a;

显式转换,也可以叫做强制类型转换。C++是强类型编程语言,每个变量的类型必需是明确的。一般的转换如下:

double a = 10.0;
int b = (int) a; /* 精度损失 */

这种显式转换方式支持任意两个类型之间转换,但任意的转换可能会导致Runtime Error。


class A { public: int num; };
classB {
    public: 
        void show() { cout << num << endl; }
        int num;
};

A a;
B *b = (B *) &a;
b->show(); /* Error */

为了解决这个问题,C++包含四种Casting操作符,对转换的类型进行限制,基本语法如下:

dynamic_cast<new_type>(expression)
reinterpret_cast<new_type>(expression)
static_cast<new_type>(expression)
const_cast<new_type>(expression)


一般来说,对于一个好的设计,应该是尽量少用强制类型转换,这里从限制最严的Casting操作符开始说起。


dynamic_cast

该操作符允许类型在继承链上向上或者向下转换,子类指针向基类指针转换是必定可以转换成功的。事实上,这也是好的设计允许的,基类指针指向子类对象(多态条件之一)。

class Base { };
class Derived: public Base { };

Derived a;
Base *b = dynamic_cast<Base *>(&a);

而对于向下转换,该操作符会在运行时检测转换是否合法。好的设计应尽量避免向下转换。对于不合法的转换,dynamic_cast返回NULL。

Base *a = new Derived();
Base *b = new Base();

Derived *pa = dynamic_cast<Derived *>(&a);
Derived *pb = dynamic_cast<Derived *>(&b); /* 返回NULL */


该操作符还支持NULL指针转换为其他指针,以及其他指针转换为void *。


static_cast

和dynamic_cast类似,static_cast也只能在继承链上向上或向下转换,但条件比前者更宽松。在向下转换过程中,static_cast不会检测转换是否合法,即上例中dynamic_cast返回NULL,而static_cast则能成功转换。

除了和dynamic_cast类似的功能外,static_cast还能对非指针类型进行转换。该转换的实质与隐式转换类似,即基础类型的转换或者是实现了复制构造函数的对象间转换。

double a = 1.25;
int b = static_cast<int>(a);


reinterpret_cast

该操作符最为宽松,允许任意指针的转换,不要求对象之间是相关的。同时还支持从整型地址和指针之间的转换。

class A { };
class B { };

A a;
B *b = reinterpret_cast<B *>(a);

const_cast

以上三个操作符都无法实现const和非const之间转换,该操作符可以转换对象的const和validate属性(设置或取消)。

const int a = 100;
int *b = const_cast<int *>(&a);

typeid

该操作符可以获取对象的类型,在头文件typeinfo中定义。返回的结果是能够最准确描述对象的类型,例如传入基类指针(指向子类对象),返回的类型是子类。返回值可以直接用于比较,判断两个对象的类型是否相同。


#include <typeinfo>

Base *a = new Base();
Base *b = new Derived();

cout << tpyeinfo(a) == typeinfo(b) << endl; /* 不相等 */
cout << typeinfo(a).name << endl;
cout << typeinfo(b).name << endl;
/* name通常是一个可读字符串,与编译器有关 */


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值