C++的四个类型转换,以下只是进行了试验而已,原理有待发掘

1、static_cast

静态类型转换,

(1)在转换的两边都是基本类型的时候,感觉和C风格的强制类型转换差不多。

float fValue = 6.5;
int i = static_cast<int>(fValue);
printf("i = %d\n", i); //输出 i= 6

(2)当转换类型为类类型的时候,在会进行一次编译器的类型检查,假设有如下代码:

class Father
{
protected:
void ProtecFunc(){ printf("this is father protect function.\n"); }
public:
void name(){ printf("this is father.\n"); }
virtual void callme(){ printf("this is father call.\n"); }
};

class Son : public Father
{
public:
void name(){ printf("this is SON.\n"); }
virtual void callme(){ printf("this is SON call.\n"); }
};

class Other
{
public:
void name(){ printf("this is Other.\n"); }
virtual void callme(){ printf("this is Other call.\n"); }
};

在进行静态类型转换的时候,编译器会对两边的类型进行检查,只有“有继承关系”的类才能通过这个检查:

Father *pFa = new Father();    
Son* pSon = static_cast<Son*>(pFa);
pSon->name(); //输出 "this is SON"
pSon->callme(); //输出 “this is father call”

Son* pSon1 = new Son();
Father *pFa1 = static_cast<Father*>(pSon1);
pFa1->name(); // 输出 "this is father"
pFa1->callme(); //输出 “this is SON call”

Other* pOther = new Other();
Father* pSon2 = static_cast<Father*>(pOther); //无法编译通过

2、const_cast

常量类型转换,const_cast 中的类型必须是指针、引用或指向对象类型成员的指针。

(1)基本类型是无法使用的,如:

int nValue = 5;
const int nCValue = const_cast<int>(nValue); //无法编译通过

(2)只能在同类型间使用, 其只能调节类型限定符const ,而不能更改基础对象类型

//可以编译通过,并正常输出
Father* pFa = new Father();
Father * const pFa1 = const_cast<Father*>(pFa);
pFa1->name();
pFa1->callme();
Father* pFa = new Father();
Father const * pFa2 = const_cast<Father*>(pFa);
pFa2->name(); //该行报错
//无法编译通过, 编译器给出的错误是 :
// 1 error C2662 : “void Father::name(void)” : 不能将“this”指针从“const Father”转换为“Father &”
// 2 IntelliSense : 对象包含与成员函数不兼容的类型限定符 对象类型是 : const Father
Son* pSon = new Son();
Father * const pFa2 = const_cast<Father*>(pSon);
//无法编译通过, 只能调节类型限定符, 不能更改基础类型
const Father*  pFa = new Father();
//Father *pFa1 = pFa; //无法编译通过, 无法从“const Father *”转换为“Father *”
Father *pFa1 = const_cast<Father*>(pFa); //编译通过

3、dynamic_cast:动态类型转换

(1) dynamic_cast 中的类型必须是指向完整类类型或 void * 的指针或引用,对基本类型使用时,是无法编译通过的

int iValue = 5;
float fValue = dynamic_cast<int>(iValue); //无法编译通过

(2)在运行时检查对象类型, 只有“存在继承关系”的对象间可以使用,子类对象可以转为父类对象,但父类对象无法转为子类对象

Father *pFa = new Father();
Son* pSon = dynamic_cast<Son*>(pFa);
if (pSon)
{
//不会进入这里执行
pSon->name();
pSon->callme();
}

Son* pSon1 = new Son();
Father *pFa1 = dynamic_cast<Father*>(pSon1);
if (pFa1)
{
//进入执行
pFa1->name(); // 输出 "this is father"
pFa1->callme(); //输出 “this is SON call”
}

Other* pOther = new Other();
Father* pFa2 = dynamic_cast<Father*>(pOther);
if (pFa2)
{
//不会进入执行
pFa2->name();
pFa2->callme();
}

OtherNoVirtual* pOtherNoVirtual = new OtherNoVirtual();
Father* pFa3 = dynamic_cast<Father*>(pOtherNoVirtual); //无法编译通过, 运行时 dynamic_cast 的操作数必须包含多态类类型

4、interpret_cast

这个使用起来和C风格的强制转换很像,既可用于基础类型,也可用于对象类型,不做任何检查,不改变值,
具体区别望大神指教:

char* pszValue = "hello.";
float fValue = reinterpret_cast<float&>(pszValue);
int iValue = reinterpret_cast<int&>(pszValue);
printf("fValue = %f, iValue=%x, pointer = %p\n", fValue, iValue, pszValue);
//输出 fValue = 0.000000, iValue=871988, pointer = 00871988

Father *pFa = new Father();
Son* pSon = reinterpret_cast<Son*>(pFa);
if (pSon)
{
//不会进入这里执行
pSon->name(); //输出 "this is SON"
pSon->callme(); // 输出 "this is father call"
}

Son* pSon1 = new Son();
Father *pFa1 = reinterpret_cast<Father*>(pSon1);
if (pFa1)
{
//进入执行
pFa1->name(); // 输出 "this is father"
pFa1->callme(); //输出 “this is SON call”
}

Other* pOther = new Other();
Father* pFa2 = reinterpret_cast<Father*>(pOther);
if (pFa2)
{
//很危险,当成另一个对象来用了
pFa2->name(); // 输出 "this is father"
pFa2->callme(); //输出 “this is Other call”
}

OtherNoVirtual* pOtherNoVirtual = new OtherNoVirtual();
Father* pFa3 = reinterpret_cast<Father*>(pOtherNoVirtual);
if (pFa3)
{
//这很危险,因为相当于使用不存在的空间
pFa3->name(); //输出 "this is father"
pFa3->callme(); //访问错误
}