說到C++類型轉換不得不說,這是必須要弄清楚的一個東西,但是有特別容易弄錯。
我們先用大字總結,以留下筆記再分析。
const_cast:
(1):<>括號裏可以是對象,基本類型,以及他們的引用,和指針。
(2):作用就是把一個常量轉換成一個全新變量返回給你,且保持和原來的常量的內存指向位置不變。
static_cast和dynamic_cast:
(1)調用虛函數時,認準對象創建的時候的類型,創建是什麼類型就調他裏面的虛函數
(2)調用普通函數,認準當前類型,使用當前類型的的函數
(3)子類->父類一般不會失敗,推薦用static_cast
(4)父類->子類可能失敗,爲了安全應使用dynamic_cast,即使失敗返回空指針
(5)父類->子類一旦使用dynamic_cast,則必須保證父類中有虛函數,否則編譯失敗;
(6)dynamic_cast<>裏只能放非基本類型的引用或指針;
(7)dynamic_cast:繼承關係的類指針對象或引用之間轉換;
(8)static_cast:基本的數據類型轉換和指針轉換;
(9)const_cast:常量對象被轉換成非常量對象,且保持指向不變;
const_cast 例子分析:
int a1=7;
const int *const p1=&a1;
這句話的正真意思是什麼呢,不是官話什麼“指向常量的常指針”,這句話話太不能理解了,實際上他就是告訴了我們以下兩件事。
1. p1不能賦值
2. *p1也不能賦值
也就是說通過以上兩種情況都不能改變a1在內存中值7,當然還有其他方法改變a1的值,比如a1自己賦值一個新的數值,這樣也改變了內存中的值。
但是還有沒有別的方法呢,這時候const_cast就可以發揮作用了。
int * p2 = const_cast<int*>(p1);//加上這句話,就可以利用p2來改變內存中a1的值了
static_cast和dynamic_cast例子源碼
#include <iostream>
#define LOG(format,...) printf(format,__VA_ARGS__);//可變參數宏
class Base
{
public :
Base(){
a=5;
}
~Base(){}
int a;
virtual void display()
{
printf("virtualMethod:field a=%d\n",a);
}
void showInfo()
{
printf("normalMethod:field a=%d\n",a);
}
};
class Derived :public Base
{
public :
Derived(){
a=10;
}
~Derived(){}
int b;
virtual void display() override
{
printf("virtualMethod:field a=%d\n",a);
}
void showInfo()
{
printf("normalMethod:field a=%d\n",a);
}
};
int main()
{
LOG("\n\n子類->父類 非指針/ \n");
{
Derived p;
Base cp=p;
cp.display();
cp.showInfo();
Base cp1=static_cast<Base>(p);
cp1.display();
cp1.showInfo();
Base cp2=static_cast<Base&>(p);
cp2.display();
cp2.showInfo();
}
LOG("\n\n子類->父類 /*Base * obj=(Base *)(new Derived())]*/ \n");
{
Derived *p=new Derived();
Base *cp=(Base *)p;
cp->display();
cp->showInfo();
(*cp).display();
(*cp).showInfo();
delete p;
}
LOG("\n\n子類->父類/*Base * obj=static_cast<Base *>(new Derived())]*/\n");
{
//在類層次間進行上行轉換時,dynamic_cast和static_cast的效果是一樣的
Derived *p=new Derived();
Base *cp=static_cast<Base *>(p);
cp->display();
cp->showInfo();
(*cp).display();
(*cp).showInfo();
delete p;
}
LOG("\n\n父類->子類/*Derived * obj=(Derived *)(new Base())]*/不安全的做法\n");
{
Base *p=new Base();
Derived *dp=(Derived *)p;
dp->display();
dp->showInfo();
(*dp).display();
(*dp).showInfo();
delete p;
}
LOG("\n\n父類->子類/*Derived * obj=static_cast<Derived *>(new Base())]*/不安全的做法\n");
{
Base *p=new Base();
Derived *dp=static_cast<Derived *>(p);
dp->display();
dp->showInfo();
(*dp).display();
(*dp).showInfo();
delete p;
}
LOG("\n\n父類->子類/*Derived * obj=dynamic_cast<Derived *>(new Base())]*/安全的做法\n");
{
Base *p=new Base();
Derived *dp=dynamic_cast<Derived *>(p);
if(dp!=nullptr)
{
dp->display();
dp->showInfo();
(*dp).display();
(*dp).showInfo();
}else
LOG("通過空指針判斷出轉換失敗\n\n");
delete p;
}
LOG("\n\n子類->父類->子類=====================\n");
{
Derived *p2=new Derived();
Base *cp=static_cast<Base *>(p2);
Derived *dp=dynamic_cast<Derived*>(cp);
//Derived *dp=static_cast<Derived*>(cp);
dp->display();
dp->showInfo();
delete p2;
}
//LOG("\n\n子類2->父類2=====================\n");
//{
// Derived2 *p2=new Derived2();
// Base2 *cp=static_cast<Base2 *>(p2);
// Derived2 *dp=dynamic_cast<Derived2*>(cp);
// //Derived *dp=static_cast<Derived*>(cp);
// dp->showInfo();
// delete p2;
//}
LOG("=========C++繼承關係總結=====================\n");
LOG("(1)調用虛函數時,誰new出來的對象,調用誰的虛函數\n");
LOG("(2)調用普通函數,目前這個是什麼類調用\n");
LOG("(3)子類->父類一般不會失敗,推薦用static_cast\n");
LOG("(4)父類->子類可能失敗,爲了安全應使用dynamic_cast,即使失敗返回空指針\n");
LOG("(5)父類->子類一旦使用dynamic_cast,則必須保證父類中有虛函數,否則編譯失敗\n");
LOG("(6)dynamic_cast<>裏只能放非基本類型的引用或指針\n");
LOG("(7)dynamic_cast:繼承關係的類指針對象或引用之間轉換,\n");
LOG("(8)static_cast:基本的數據類型轉換和指針轉換\n");
LOG("(9)const_cast:常量對象被轉換成非常量對象,且保持指向不變\n");
}