作者:jicanmeng
时间:2017年06月20日
In C++, there are 5 different types of casts: C-style casts, static casts, const casts, dynamic casts, and reinterpret casts.
Const casts and reinterpret casts should generally be avoided because they are only useful in rare cases and can be harmful if used incorrectly. 本文不会讨论这两种转换。
传统的C-style类型转换的缺点如下:
Because C-style casts are not checked by the compiler at compile time, C-style casts can be inherently misused, because they will let you do things that may not make sense, such as getting rid of a const or changing a data type without changing the underlying representation (leading to garbage results). Consequently, C-style casts should generally be avoided.
不过在我看来,C-style和static_cast也没啥区别啊,都是告诉编译器进行显式的类型转换。如下面的例子:
#include <iostream> int main() { float a = 3.2f; // int b = (int)a; int b = static_cast<int>(a); std::cout << b << std::endl; return 0; }
第6行和第7行都可以。如果不加类型转换,会有警告:warning C4244: “初始化”: 从“float”转换到“int”,可能丢失数据
。
dynamic_cast最常见的用法是将指向父类的指针进行转换,然后赋值给指向子类的指针。
#include <iostream> #include <string> class Base { protected: int m_value; public: Base(int value) : m_value(value) { } virtual ~Base() {} }; class Derived : public Base { protected: std::string m_name; public: Derived(int value, std::string name) : Base(value), m_name(name) { } const std::string& getName() { return m_name; } }; Base* getObject(bool bReturnDerived) { if (bReturnDerived) return new Derived(1, "Apple"); else return new Base(2); } int main() { Base *b = getObject(true); Derived *d = dynamic_cast(b); // use dynamic cast to convert Base pointer into Derived pointer if (d) { std::cout << "The name of the Derived is: " << d->getName() << '\n'; } delete b; return 0; }
以下是运行结果:
[jicanmeng@andy tmp]$ ./a.out
The name of the Derived is: Apple
[jicanmeng@andy tmp]$
dynamic_cast也可以用于引用。将上面的程序稍微修改一下:
#include <iostream> #include <string> class Base { protected: int m_value; public: Base(int value) : m_value(value) { } virtual ~Base() {} }; class Derived : public Base { protected: std::string m_name; public: Derived(int value, std::string name) : Base(value), m_name(name) { } const std::string& getName() { return m_name; } }; Base* getObject(bool bReturnDerived) { if (bReturnDerived) return new Derived(1, "Apple"); else return new Base(2); } int main() { Base *b = getObject(true); Derived &d = dynamic_cast<Derived>(*b); // use dynamic cast to convert Base reference into Derived reference std::cout << "The name of the Derived is: " << d.getName() << '\n'; delete b; return 0; }
learncpp.com上面是这样说的:
Because C++ does not have a “null reference”, dynamic_cast can’t return a null reference upon failure. Instead, if the dynamic_cast of a reference fails, an exception of type std::bad_cast is thrown.
所以,对于上面的这个程序,如果在调用getObject()函数时传递的是false,那么程序就会运行终止并退出。可以使用前面文章中提到的"exception handling"来进行处理。比如修改为如下的形式:
#include <iostream> #include <string> class Base { protected: int m_value; public: Base(int value) : m_value(value) { } virtual ~Base() {} }; class Derived : public Base { protected: std::string m_name; public: Derived(int value, std::string name) : Base(value), m_name(name) { } const std::string& getName() { return m_name; } }; Base* getObject(bool bReturnDerived) { if (bReturnDerived) return new Derived(1, "Apple"); else return new Base(2); } int main() { Base *b = getObject(false); try { Derived &d = dynamic_cast<Derived>(*b); // use dynamic cast to convert Base reference into Derived reference std::cout << "The name of the Derived is: " << d.getName() << '\n'; } catch (std::bad_cast) { std::cout << "bad cast from Base to Derived" << std::endl; } delete b; return 0; }
以下是运行结果:
[jicanmeng@andy tmp]$ ./a.out
bad cast from Base to Derived
请按任意键继续. . .
[jicanmeng@andy tmp]$
对于static_cast和dynamic_cast有如下的简单总结: