恩,这四个cast,之前一直没怎么搞懂,在使用类型转化时仍然经常使用C风格的转化,而且之前的一次笔试题竟然考的就是这道题,好吧,我强迫症又犯了,一定要彻底搞懂...
一.概述
1.(typename)element:C风格的强制转化,貌似通吃,但是既然用了C++,还有分门别类的cast,是时候放弃这个了。
2. static_cast<typename>(element):通常转换,没有运行时的检测,在不知道用哪个的时候用这个就好了。
3. dynamic_cast<typename>(element) :动态转换,有运行时检测,通常在基类和派生类之间转换时使用。
4. const_cast<typename>(element):主要针对const和volatile的转换,去除const属性
5. reinterpret_cast<typename>(element):用于没有任何关联的类型转换,慎用
俗话说得好,实践是检验真理的唯一标准,要想清楚的知道每种转化会发生什么,最好的办法就是写个demo,而不是看别人的blog怎么写,自己就怎么说,这样印象不深刻,而且可能人云亦云,没有自己的想法。
二.static_cast
// C++Test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class CastTestBase
{
public:
CastTestBase(string n):name(n)
{
}
~CastTestBase()
{
}
void ShowBase()
{
cout<<"show base, name is : "<<name<<endl;
}
private:
string name;
};
class CastTestChild : public CastTestBase
{
public:
CastTestChild(string n, string cn) : CastTestBase(n), childname(cn)
{
}
~CastTestChild()
{
}
void ShowChild()
{
cout<<"show child, name is: "<<childname<<endl;
}
private:
string childname;
};
void TestFunc1(int* num)
{
cout<<"num is "<<*num<<endl;
}
void TestFunc2(void* pointer)
{
cout<<"num is "<<(*static_cast<int*>(pointer))<<endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
//static_cast转换内置数据类型
int a = 10;
char b = static_cast<char>(a);
//void*型指针转化为其他类型指针
void* pointer = new int(1);
TestFunc1(static_cast<int*>(pointer));
//其他任何类型指针转化为void*型指针
int* num = new int(2);
TestFunc2(num);
//子类指针转化为父类指针(安全,不写static_cast也可以执行隐式转换)
CastTestBase* basePointer = static_cast<CastTestBase*>(new CastTestChild("child", "child"));
basePointer->ShowBase();
//父类指针转化为子类指针(不一定安全,如果调用子类特有的内容会出错)
CastTestChild* childPointer = static_cast<CastTestChild*>(new CastTestBase("base"));
//childPointer->ShowChild();//这样会出错的,父类并没有childname字段。而如果只调用函数没有问题,使用字段会出现问题
childPointer->ShowBase();
system("pause");
return 0;
}
结果:
num is 2
show base, name is : child
show base, name is : base
请按任意键继续. . .
//childPointer->ShowChild();//这样会出错的,父类并没有childname字段。而如果只调用函数没有问题,使用字段会出现问题
这句如果运行,会有问题,即编译不会出错,不会检查类型转换的问题,在运行时直接崩掉。
三.dynamic_cast
// C++Test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class CastTestBase
{
public:
CastTestBase(string n):name(n)
{
}
~CastTestBase()
{
}
void ShowBase()
{
cout<<"show base in base, name is : "<<name<<endl;
}
virtual void ShowChild()
{
cout<<"show child in base"<<endl;
}
private:
string name;
};
class CastTestChild : public CastTestBase
{
public:
CastTestChild(string n, string cn) : CastTestBase(n), childname(cn)
{
}
~CastTestChild()
{
}
virtual void ShowChild() override
{
cout<<"show child in child, name is: "<<childname<<endl;
}
private:
string childname;
};
int _tmain(int argc, _TCHAR* argv[])
{
//子类指针转化为父类指针(安全,不写static_cast也可以执行隐式转换)
CastTestBase* basePointer = dynamic_cast<CastTestBase*>(new CastTestChild("child", "child"));
basePointer->ShowBase();
basePointer->ShowChild();
//父类指针转化为子类指针(不一定安全,如果调用子类特有的内容会出错)
CastTestChild* childPointer = dynamic_cast<CastTestChild*>(new CastTestBase("base"));
if (childPointer)//dynamic_cast的返回值可能是NULL,切记!!!
{
childPointer->ShowBase();
childPointer->ShowChild();//这样会出错的,父类并没有childname字段。而如果只调用函数没有问题,使用字段会出现问题
}
else
cout<<"dynamic_cast failed!"<<endl;
system("pause");
return 0;
}
show child in child, name is: child
dynamic_cast failed!
请按任意键继续. . .
四.const_cast
int _tmain(int argc, _TCHAR* argv[])
{
const int a = 10;
//a = 20;不能修改常量
//int b = const_cast<int>(a);<>中的即要转化的对象必须是指针或者引用
int* b = const_cast<int*>(&a);
//int* b = &a;const int 类型的实体不能使用int*类型的指针指向
*b = 20;
cout<<*b<<endl;
//int& c = a;非const引用不能引用const变量
int& c = const_cast<int&>(a);
c = 30;
cout<<c<<endl;
system("pause");
return 0;
}
五.reinpreter_cast
参考链接:http://m.blog.csdn.net/blog/pizi0475/46794631
http://blog.csdn.net/starryheavens/article/details/4617637