C++中若類中沒有預設建構函式,如何使用物件陣列
阿新 • • 發佈:2019-08-24
前言:
如果定義一個類,有其預設的建構函式,則使用new動態例項化一個物件陣列,不是件難事,如下程式碼:
1 #include <memory> 2 #include <iostream> 3 4 using namespace std; 5 6 class Animal 7 { 8 public: 9 #if 1 //用於後面演示,無預設建構函式 10 Animal() : num(0) 11 { 12 cout << "Animal constructor default" << endl; 13 } 14 #endif 15 Animal(int _num) : num(_num) 16 { 17 cout << "Animal constructor param" << endl; 18 } 19 20 ~Animal() 21 { 22 cout << "Animal destructor" << endl; 23 } 24 25 void show() 26 { 27 cout << this->num << endl; 28 } 29 30 private: 31 int num; 32 }; 33 34 int main() 35 { 36 Animal *ani = new Animal[5]; 37 38 delete[]ani; 39 40 system("pause"); 41 return 0; 42 }
執行結果:
但是,如果沒有預設建構函式,會出現怎麼樣呢?
看下圖報錯提示:
那要如何例項化一個沒有預設建構函式的物件陣列呢?
下面我將介紹兩種方法:
1. 使用C++11新特性allocator類
2. 使用placement new 即operator new(第三個過載版本)void* operator new(size_t size, void *p)函式
一、allocator類
對於allocator類,請看 我的另一篇blog http://www.cnblogs.com/SimonKly/p/7819122.html
請看一下程式碼關於使用如何實現無預設建構函式,動態例項化物件陣列的allocator方法
1 //#include "CAnimal.h" 2 #include <memory> 3 #include <iostream> 4 5 using namespace std; 6 7 class Animal 8 { 9 public: 10 #if 1 //即使為0,沒有預設構造也是可以, 11 Animal() : num(0) 12 { 13 cout << "Animal constructor default" << endl; 14 } 15 #endif 16 Animal(int _num) : num(_num) 17 { 18 cout << "Animal constructor param" << endl; 19 } 20 21 ~Animal() 22 { 23 cout << "Animal destructor" << endl; 24 } 25 26 void show() 27 { 28 cout << this->num << endl; 29 } 30 31 private: 32 int num; 33 }; 34 35 /* 36 由於allocator將記憶體空間的分配和物件的構建分離 37 故使用allocator分為以下幾步: 38 1.allocator與類繫結,因為allocator是一個泛型類 39 2.allocate()申請指定大小空間 40 3.construct()構建物件,其引數為可變引數,所以可以選擇匹配的建構函式 41 4.使用,與其它指標使用無異 42 5.destroy()析構物件,此時空間還是可以使用 43 6.deallocate()回收空間 44 */ 45 46 int main() 47 { 48 allocator<Animal> alloc; //1. 49 Animal *a = alloc.allocate(5); //2. 50 51 //3. 52 alloc.construct(a, 1); 53 alloc.construct(a + 1); 54 alloc.construct(a + 2, 3); 55 alloc.construct(a + 3); 56 alloc.construct(a + 4, 5); 57 58 //4. 59 a->show(); 60 (a + 1)->show(); 61 (a + 2)->show(); 62 (a + 3)->show(); 63 (a + 4)->show(); 64 65 //5. 66 for (int i = 0; i < 5; i++) 67 { 68 alloc.destroy(a + i); 69 } 70 //物件銷燬之後還可以繼續構建,因為構建和記憶體的分配是分離的 71 //6. 72 alloc.deallocate(a, 5); 73 74 cin.get(); 75 return 0; 76 }
執行結果
通過執行結果可以看出,無論是否有預設構造,allocator會選擇出最匹配的建構函式(過載)
二、placement new
函式原型:
void* operator new(size_t size, void* p) throw();
函式執行忽略size,只返回p指標,不分配記憶體。
placement new具體的用法和相關技術點,請參看我的另一篇博文的第三節
http://www.cnblogs.com/SimonKly/p/7826651.html
具體實現:C++中若類中沒有預設建構函式,如何使用物件陣列??
請看下面的程式碼:
1 #include <iostream> 2 3 using namespace std; 4 5 class animal 6 { 7 public: 8 #if 1 //用於後面演示,無預設建構函式 9 animal() : num(0) 10 { 11 cout << "animal constructor default" << endl; 12 } 13 #endif 14 animal(int _num) : num(_num) 15 { 16 cout << "animal constructor param" << endl; 17 } 18 19 ~animal() 20 { 21 cout << "animal destructor" << endl; 22 } 23 24 void show() 25 { 26 cout << this->num << endl; 27 } 28 29 void * operator new(size_t size, void *p) 30 { 31 return p; 32 } 33 34 private: 35 int num; 36 }; 37 38 39 int main(int args, char ** argv) 40 { 41 // 一個動態animal陣列 42 void *p = operator new(5 * sizeof(animal)); // 申請緩衝器 43 animal *a = static_cast<animal *>(p); // 轉換型別 44 45 // 2.物件構建 46 for (int i = 0; i < 4; i++) 47 { 48 new(a + i) animal(i);// 呼叫過載構造 49 } 50 new(a + 4) animal; // 也可以呼叫預設構造 51 52 // 3.使用 53 for (int i = 0; i < 5; i++) 54 { 55 (a + i)->show(); 56 } 57 58 // 4.銷燬物件 59 for (int i = 0; i < 5; i++) 60 { 61 (a + i)->~animal(); 62 } 63 64 // 5.回收空間 65 delete[]p; 66 67 cin.get(); 68 return 0; 69 }
執行結果:
通過執行結果可以看出,無論是否有預設構造,placement new會向已經申請的空間