C++是一门弱类型的语言,提供了许多复杂和灵巧类型转换的方式。笔者之前写的Python与Go都是强类型的语言,对这种弱类型的设计实在是接受无力啊~~ ( 生活所迫,工作还得写C++啊~~)C++语言提供了四种类型转换的操作:static_cast,dynamic_cast,reinterpret_cast,const_cast,今天就来聊一聊,在C++之中应该如何来使用这些类型转换的。

1.旧式类型转换

开门见山,先聊聊笔者对类型转换的看法吧。从设计上看,一门面向对象的语言是不一样提供类型转换的,这种方式破坏了类型系统。C++为了兼容C也不得不吞下这个苦果,在实际进行编程工作的过程之中,并不太推荐大家使用类型转换。(Java在这里就做了一些妥协,在基本类型之中提供了类型转换。对于对象类型则不提供类型转换这种黑魔法

C++之中提供了两种类型转换的方式,第一种方式沿用了C语言之中的类型转换,称之为旧式类型转换。说起来也很简单,举个栗子:

char x = 'c';
int y = (int) x;

这是最简单的一个旧式类型转换,一个char类型被装换为一个int类型。但是这种旧式的类型转换是存在问题的:过于粗暴且极易失控,所以C++新提供了四种新式的类型转换来替代旧式的类型转换,这四种类型转换分别用于不用的转换场景,接下来笔者来一一梳理一下它们的用法。

2.新式的类型转换

C++语言提供了四种新式类型转换的操作:

static_cast,dynamic_cast,reinterpret_cast,const_cast,这些操作都依托了C++的模板来使用,标准的用法是

xxx_cast<转换类型>(转换参数)

这种新式转换优于旧式的转换就在于:编译器可以在转换期间进行更多的检查,对于一些不符合转换逻辑的转换进行一些纠错。而某些类型转换操作可以利用RTTI(运行时类型信息)来确保类型转换的合理,这是旧式的类型转换无法达成的效果。

  • const_cast

从名字上就可以看出来,这厮是用来对const属性进行类型转换的。这个名字取得有些偏颇,它同样适用于volatile属性。它可以为变量添加或接触上述属性,它也是新式转换之中唯一具有这个能力的转换方式,没有什么额外的坑,用户体验良好:(但是偶尔对于const属性的转换需要执行多步,先通过const_cast转换,再借助其他转换

//函数需要传递const属性的变量,如atoi
atoi(const_cast<const char*>(char_ptr))
  • static_cast

static_cast 是静态的转换形式,不通过运行时类型检查来保证转换的安全性。它主要用于如下场合:

  • 用于基本数据类型之间的转换,如把long转换成char,把int转换成char。

  • 用于面向对象编程之中基类与派生类之间的指针或引用转换。它分为两种

    上行转换(把派生类的指针或引用转换成基类)是安全的;

    下行转换(把基类指针或引用转换成派生类),由于没有运行时的动态类型检查,所以是不安全的。

  • 把非const属性的类型转换为const类型,但是不能将const类型转换为非const类型,这个得借助前文的const_cast。

  • void 的空指针转换成其他类型的的空指针。

上面的几种概念的比较好理解,这里笔者着重聊聊上下行转换:不啰嗦,看代码:

class Bird {
public:
virtual void fly() {
cout << "I can fly." << endl;
}
}; class Penguin:public Bird {
public:
void fly() {
cout << "I can't fly." << endl;
}
};

上述代码我们定义了两个类BirdPenguin

int main() {
Penguin* p = new (std::nothrow) Penguin;
Bird* b = static_cast<Bird *>(p); b->fly();
return 0;
}

上行转换,将派生类转换为基类的指针,合法。

int main() {
Bird* b = new (std::nothrow) Bird;
Penguin* p = static_cast<Penguin *>(b); if (p != nullptr) {
p->fly();
} else { }
return 0;
}

下行转换,将基类转换为派生类的指针,此时程序的行为是不确定的。并且编译期间并没有警告,这是一种十分危险的用法,所以使用时一定要谨小慎微。所以接下来就要请出下一种转换dynamic_cast,这是在对象基类和派生类之间转换推荐的一种方式。

  • dynamic_cast

dynamic_cast主要用于在类层次间进行上下行转换时,它与static_cast的最大的区别就在于dynamic_cast能够在运行时进行类型检查的功能,所以做起类型转换比static_cast更安全,但是dynamic_cast会耗费更多的系统资源。dynamic_cast是无法通过旧式类型转换完成的类型转换。

int main() {
Bird* b = new (std::nothrow) Bird;
Penguin* p = dynamic_cast<Penguin *>(b);
if (p != nullptr) {
p->fly();
} else {
cout << "cast failed" << endl;
}
return 0;
}

dynamic_cast对于非法的下行转换会返回空指针,所以可以在一定程度上避免不安全的类型转换。

  • reinterpret_cast

    reinterpret_cast主要用于指针类型之间的转换,和对象到指针类型之间的转换。reinterpret就是对数据的比特位重新解释转换为我们需要转换的对象。其与static_cast的区别在于其能处理有继承关系类的指针和内置数据类型的转换。而reinterpret_cast能够处理所有指针(引用)之间的转换
int main() {
Bird* b = new (std::nothrow) Bird;
Penguin* p = reinterpret_cast<Penguin *>(b);
if (p != nullptr) {
p->fly();
} else {
cout << "cast failed" << endl;
}
return 0;
}

上述代码依旧可以转换成功,结果不可控

3.小结

梳理完C++新引进的四种类型转换符之后,想必大家在实践之中可以很好的运用好这些C++的类型转换。后续笔者还会继续深入的探讨有关C++之中类型系统相关的内容,欢迎大家多多指教。

C++雾中风景11:厘清C++类型转换(static_cast,dynamic_cast,reinterpret_cast,const_cast)的更多相关文章

  1. c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast

    c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast  [版权声明]转载请注明出处 http://www.cnblogs.c ...

  2. C++ static_cast dynamic_cast reinterpret_cast const_cast转换

    static_cast <type-id> ( expression ) 和C风格的类型转换相似,可以转换一个指针到基类,或者派生类.不做Run-time类型检查,这样转换并不总是安全的. ...

  3. static_cast, dynamic_cast, reinterpret_cast, const_cast区别比较

    隐式转换(implicit conversion) ; int b; b=a; short是两字节,int是四字节,由short型转成int型是宽化转换(bit位数增多),编译器没有warning,如 ...

  4. static_cast, dynamic_cast, reinterpret_cast, const_cast的区别

    static_cast最像C风格的强制转换,很多时候都需要程序员自身去判断转换是否安全.但是相对C风格的强制转换,在无关类的类指针之间转换上,有安全性的提升. dynamic_cast是运行时的转换吧 ...

  5. c++强制类型转换:dynamic_cast、const_cast 、static_cast、reinterpret_cast

    c++强制类型转换:dynamic_cast.const_cast .static_cast.reinterpret_cast 博客分类: C/C++ CC++C#编程数据结构  dynamic_ca ...

  6. reinterpret_cast,static_cast, dynamic_cast,const_cast的运用分析

    reinterpret_cast(重新解释类型转换) reinterpret_cast 最famous的特性就是什么都可以,转换任意的类型,包括C++所有通用类型,所以也最不安全 应用 整形和指针之间 ...

  7. 你也许还不知道const_cast,static_cast,dynamic_cast,reinterpret_cast的区别吧?

    [QQ群: 189191838,对算法和C++感兴趣可以进来]       开篇立意: C++中各种转换令人眼花缭乱,看似差不多,实际差很多,而且在当今时间,做一个"差不多先生"其 ...

  8. C++中四种类型转换方式(ynamic_cast,const_cast,static_cast,reinterpret_cast)

    Q:什么是C风格转换?什么是static_cast, dynamic_cast 以及 reinterpret_cast?区别是什么?为什么要注意? A:转换的含义是通过改变一个变量的类型为别的类型从而 ...

  9. 【C++】 四种强制类型转换(static_cast 与 dynamic_cast 的区别!)

    强制类型转换 1. static_cast 2. dynamic_cast 3. const_cast 4. reinterpret_cast 5. 为什么要需要四种类型转换? 1. static_c ...

随机推荐

  1. MySQL备份可能遇到的坑

    MySQL备份工具,支持各种参数选项,使用不同的选项极有可能影响备份处理过程.本文使用我们常规认为合理的备份参数,测试/验证是否存在容易忽视的坑 # 常规备份参数 # mysqldump shell& ...

  2. 交换机console口连接

    http://www.webkaka.com/info/archives/knowledge/2010/08/30452/

  3. C - Musical Theme (后缀数组)

    题目链接:https://cn.vjudge.net/contest/283743#problem/C 题目大意:给你n个数组,然后问你是否有多个“相似”且不重叠的子串的长度大于等于5(两个子串相似当 ...

  4. mysql 查询优化 ~explain解读之type的解读

    一 简介:今天咱们来聊聊explain中type的相关解读 二 类型: system: 表中只有一条数据. 这个类型是特殊的 const 类型.  const: 针对主键或唯一索引的等值查询扫描, 最 ...

  5. 【C++】解决vs2015经常卡顿的办法

    VS2015经常性的卡顿,参考了zhihu里问答的办法,编译和使用的时候的确快多了 为什么vs2015经常卡顿? https://www.zhihu.com/question/34911426 感谢z ...

  6. 【转】深入浅出JMS(三)--ActiveMQ简单的HelloWorld实例

    这篇博文,我们使用ActiveMQ为大家实现一种点对点的消息模型.如果你对点对点模型的认识较浅,可以看一下第一篇博文的介绍. JMS其实并没有想象的那么高大上,看完这篇博文之后,你就知道什么叫简单,下 ...

  7. nagios系列(五)之nagios图形显示的配置及自定义插件检测密码是否修改详解

    nagios图形显示的配置 在服务端安装相关软件 #1.图形显示管理的依赖库 yum install cairo pango zlib zlib-devel freetype freetype-dev ...

  8. 16-client、offset、scroll系列

    1.client系列 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"& ...

  9. 第一个Spring Boot程序

    Windows 10家庭中文版,java version "1.8.0_152", Eclipse Oxygen.1a Release (4.7.1a),Spring Tools ...

  10. 恋爱Linux(Fedora20)1——安装开启ssh服务

    1) 安装openssh-server # yum install openssh-server 2) 查看是否已成功安装openssh-server # rpm -qa | grep openssh ...