C++ 語法實驗室之const_cast,static_cast,dynamic_cast

說到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");

}







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章