void*指針ios
void關鍵字表示「空類型」的概念。可是,這裏的「空類型」不表示「任意類型」,而是表示不存在的意思,也就是說C/C++不容許你寫語句void a,不存在類型爲void的東西.c++
void*表示「空類型指針」,與void不一樣,void*表示「任意類型的指針」或表示「該指針與一地址值相關,可是不清楚在此地址上的對象的類型」。程序員
類型轉換安全
C風格轉換:函數
1 int i; 2 double d; 3 4 i = (int) d; 5 //或 6 i = int (d);
C風格轉換在C++中是適用的。可是C++也提供了4種轉換方法。this
那爲何還須要一個新的C++類型的強制轉換呢?spa
新類型的強制轉換能夠提供更好的控制強制轉換過程,容許控制各類不一樣種類的強制轉換。C++中風格是static_cast<type>(content)。C++風格的強制轉換其餘的好處是,它們能更清晰的代表它們要幹什麼。程序員只要掃一眼這樣的代碼,就能當即知道一個強制轉換的目的。指針
C++轉換:code
static_cast(exp)對象
用於相關類型之間的轉換,諸如:在同一個類的繼承層次關係中,向上或向下轉換;枚舉類型與整數類型之間的轉換;浮點類型與指數類型之間的轉換。
static_cast它能在內置的數據類型間互相轉換,對於類只能在有聯繫的指針類型間進行轉換。能夠在繼承體系中把指針轉換來、轉換去,可是不能轉換成繼承體系外的一種類型
1 class A { ... }; 2 class B { ... }; 3 class D : public B { ... }; 4 void f(B* pb, D* pd) 5 { 6 D* pd2 = static_cast<D*>(pb); // 不安全, pb可能只是B的指針 7 B* pb2 = static_cast<B*>(pd); // 安全的 8 A* pa2 = static_cast<A*>(pb); //錯誤A與B沒有繼承關係 9 ... 10 }
reinterpret_cast(exp)
字面理解即re-interpret,從新解析(釋)的意思。故名思意,它主要用於不相關類型之間的轉換,好一個英文單詞在不一樣的上下文中,詞性和詞義可能徹底不一樣。它爲不一樣類型之間轉換帶來的便利,可是也伴隨着風險的,如將一個十六進制整數轉換爲內存地址(由int-->指針類型,這兩種類型徹底不關聯)。既然是用於不相關類型之間的轉換,也就意味着編譯器不會作太多的確認和承諾。
reinterpret_cast方式還有一個特色就是:目標和原始值之間至少有相同的位數,咱們能夠將轉換以後的值再轉換回去,而不像其它3種類型可能會致使精度丟失。
dynamic_cast(exp)
一種運行時(run-time)檢測的類型轉換,所以轉換可能須要較大的運行時代價,這種類型也是用C-style是沒法實現的。主要用於執行類型向下轉換和繼承之間的轉換。
dynamic_cast 僅能應用於指針或者引用,不支持內置數據類型
表達式dynamic_cast<T*>(a) 將a值轉換爲類型爲T的對象指針。若是類型T不是a的某個基類型,該操做將返回一個空指針。
它不只僅像static_cast那樣,檢查轉換先後的兩個指針是否屬於同一個繼承樹,它還要檢查被指針引用的對象的實際類型,肯定轉換是否可行。
const_cast(exp)
用於消除變量的const限定,轉換以後的變量就再也不具備「const」了,若是是一個const指針的話,轉換以後能夠改變指向而指向其它對象。
說明:
一般狀況下dynamic_cast最好些,它檢查的更嚴格些,其次是static_cast,然後二者也就是const_cast和reinterpret_cast較以前二者貌似不太經常使用,並且也不推薦使用,const_cast在用於去除const的地方仍是有所發揮的,reinterpret_cast在轉換時,不會在內存中進行補足比特位(例如int轉換到double,須要補足4字節),這每每是不安全的,並且代碼也是不可移植的。
動態內存分配
通常來講,編譯器將內存分爲三部分:靜態存儲區域、棧、堆。靜態存儲區主要保存全局變量和靜態變量,棧存儲調用函數相關的變量、地址等,堆存儲動態生成的變量。 在c中是指由malloc,free運算產生釋放的存儲空間,在c++中就是指new和delete運算符做用的存儲區域。
對象建立的兩種方式:
類示例:
1 #include <iostream> 2 using namespace std; 3 4 class TestNew 5 { 6 private: 7 int ID; 8 public: 9 TestNew(int ID); 10 ~TestNew(); 11 }; 12 13 TestNew::TestNew(int ID) 14 { 15 this->ID = ID; 16 } 17 18 TestNew::~TestNew() 19 { 20 std::cout<<"對象 "<<this->ID<<" 執行析構函數"<<std::endl; 21 }
方法一:
ClassName object(param);
1 TestNew test(1);
這樣就聲明瞭一個ClassName類型的object對象,C++會爲它分配足夠的存放對象全部成員的存儲空間。
這種方法建立的對象,內存分配是分配到棧中的,由C++缺省建立和撤銷,自動調用構造函數和析構函數。
該方法建立的對象調用類方法時,必須用「.」,而不能用「->」。
在函數中使用該方法時,函數內局部變量的存儲單元都在棧上建立,函數執行結束後在將這些局部變量的內存空間回收。
在棧上分配內存空間效率很高,可是分配的內存容量有限。
方法二:
ClassName *object=new ClassName(param);
delete object;
1 TestNew *pTest = new TestNew(1); 2 delete pTest;
C++用new建立對象時返回的是一個對象指針,object指向一個ClassName的對象,C++分配給object的僅僅是存放指針值的空間。
用new 動態建立的對象必須用delete來撤銷該對象。只有delete對象纔會調用其析構函數。
new建立的對象不是用「*」或「.」來訪問該對象的成員函數的,而是用運算符「->」;
new建立類對象特色: