C++是一门弱类型的语言,提供了许多复杂和灵巧类型转换的方式。笔者以前写的Python与Go都是强类型的语言,对这种弱类型的设计实在是接受无力啊~~ ( 生活所迫,工做还得写C++啊~~)C++语言提供了四种类型转换的操做:static_cast,dynamic_cast,reinterpret_cast,const_cast,今天就来聊一聊,在C++之中应该如何来使用这些类型转换的。编程
####1.旧式类型转换安全
开门见山,先聊聊笔者对类型转换的见解吧。从设计上看,一门面向对象的语言是不同提供类型转换的,这种方式破坏了类型系统。C++为了兼容C也不得不吞下这个苦果,在实际进行编程工做的过程之中,并不太推荐你们使用类型转换。(Java在这里就作了一些妥协,在基本类型之中提供了类型转换。对于对象类型则不提供类型转换这种黑魔法)函数
C++之中提供了两种类型转换的方式,第一种方式沿用了C语言之中的类型转换,称之为旧式类型转换。提及来也很简单,举个栗子:ui
char x = 'c'; int y = (int) x;
这是最简单的一个旧式类型转换,一个char类型被装换为一个int类型。可是这种旧式的类型转换是存在问题的:过于粗暴且极易失控,因此C++新提供了四种新式的类型转换来替代旧式的类型转换,这四种类型转换分别用于不用的转换场景,接下来笔者来一一梳理一下它们的用法。设计
####2.新式的类型转换指针
C++语言提供了四种新式类型转换的操做: static_cast,dynamic_cast,reinterpret_cast,const_cast,这些操做都依托了C++的模板来使用,标准的用法是code
xxx_cast<转换类型>(转换参数)
这种新式转换优于旧式的转换就在于:编译器能够在转换期间进行更多的检查,对于一些不符合转换逻辑的转换进行一些纠错。而某些类型转换操做能够利用RTTI(运行时类型信息)来确保类型转换的合理,这是旧式的类型转换没法达成的效果。对象
从名字上就能够看出来,这厮是用来对const属性进行类型转换的。这个名字取得有些偏颇,它一样适用于volatile属性。它能够为变量添加或接触上述属性,它也是新式转换之中惟一具备这个能力的转换方式,没有什么额外的坑,用户体验良好:(可是偶尔对于const属性的转换须要执行多步,先经过const_cast转换,再借助其余转换)继承
//函数须要传递const属性的变量,如atoi atoi(const_cast<const char*>(char_ptr))
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; } };
上述代码咱们定义了两个类Bird与Penguin:
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主要用于在类层次间进行上下行转换时,它与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对于非法的下行转换会返回空指针,因此能够在必定程度上避免不安全的类型转换。
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++之中类型系统相关的内容,欢迎你们多多指教。