C++的代理類
怎樣在一個容器中包含型別不同,但是彼此有關係的物件?眾所周知,C++的容器只能存放型別相同的元素,所以直接在一個容器中儲存不同型別的物件本身是不可能的,只能透過以下兩種方案實現:
1. 提供一個間接層,在容器中存放物件的指標而不是物件本身。
2. 透過代理類實現。
class Animal {public: virtual void Eat() = 0; };class Cat : public Animal{};class Dog : public Animal{};class Bird : public Animal{};
在上面我們看到有一個虛基類和三個繼承類,下面分別用兩種方案來實現一個容器存放不同型別但又互相關聯的類。
1.透過指標實現
Animal* animals_array[3]; Cat cat; Dog dog; Bird bird; animals_array[0] = &cat; animals_array[1] = &dog; animals_array[2] = &bird;
這樣會帶來一個問題,就是容器中的指標指向的物件如果被銷燬,這個指標就會變成野指標,就像下面這樣:
Animal* animals_array[3];do{ Cat cat; Dog dog; Bird bird; animals_array[0] = &cat; animals_array[1] = &dog; animals_array[2] = &bird; }while(0);//此時物件已經被析構,容器中的指標指向未知內容
也可以換一種方式,構造一個新的動態物件,將其地址放在容器中,這樣就可以避免物件析構導致指標失效的問題:
Cat cat; animals_array[0] = new Cat(cat);
這樣會曾加額外的記憶體開銷,並且可能出現容器中兩個指標同時指向一個物件的情況。
所以,在容器中存放不同物件的指標並不是一個很好的解決方案。
2.透過代理類實現
實現程式碼如下:
class Animal {public: virtual void Eat() = 0; //copy函式,構造一個基於自身物件型別的物件 virtual Animal* copy() const = 0; virtual ~Animal() {} };class Cat : public Animal {public: virtual void Eat() { std::cout copy() : nullptr; } ~AnimalSurrogate() { if (pa != nullptr) { delete pa; pa = nullptr; } } //過載 = 運算子 AnimalSurrogate& operator=(const AnimalSurrogate& ani_srg) { if (this != &ani_srg) { delete pa; pa = ani_srg.pa != nullptr ? ani_srg.pa->copy() : nullptr; } return *this; } //將基類中的公共函式搬過來,這樣就可以透過代理類直接訪問這些方法 void Eat() { if (pa == nullptr) { throw "empty AnimalSurrogate.Eat()"; } return pa->Eat(); }private: Animal* pa;//儲存基類的指標};
透過程式碼可以看出來,所謂的代理類,就是構造一個新的類,這個類中包含關聯的基類型別的指標,該指標可以指向不同型別但又相互關聯的子類物件,透過指標可以轉調物件的方法,同時實現記憶體的管理。代理類的實用方法如下:
Cat cat; Dog dog; Bird bird; arr[0] = AnimalSurrogate(cat); arr[1] = AnimalSurrogate(dog); arr[2] = AnimalSurrogate(bird); arr[0].Eat();//輸出 cat eat.arr[1].Eat();//輸出 dog eat.arr[2].Eat();//輸出 bird eat.
總結:代理類的的每個物件都代表另一個物件,該物件可以使位於一個完成繼承層次中的任何類的物件。透過在容器中用代理物件而不是物件本身的方式,實現容器中存放不同型別的物件。
使用代理類的優缺點如下:
優點:使用代理類比直接在容器中存放不同物件的指標更安全,便於實現記憶體管理。
缺點:記憶體開銷太大,放入容器的每個物件都需要複製一次,不夠靈活。
為了避免物件的複製,可以透過控制程式碼類來實現,關於控制程式碼類的原理和使用在下一篇問文章中作介紹。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/506/viewspace-2801659/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- C++ 類的大小C++
- C++中的容器類C++
- 探究 Kotlin 類代理Kotlin
- Java類關係之代理(代理模式)Java模式
- c++類與類的聚合(Aggregation)關係C++
- C++ 類 & 物件C++物件
- C++分類C++
- C++:類的成員函式C++函式
- C++:類的靜態成員C++
- 【C++】兩個類的相互引用C++
- c++類的靜態成員C++
- 在spring中獲取代理物件代理的目標物件工具類Spring物件
- [C++之旅] 7 C++類和物件C++物件
- C++設計模式之代理模式C++設計模式
- C++ | 類繼承C++繼承
- C++ 類和物件C++物件
- c++類和物件C++物件
- C++類和物件是什麼?C++類和物件詳解C++物件
- http代理有哪些類別?HTTP
- c++ 類的函式引用 指標C++函式指標
- C++派生類的拷貝構造C++
- 載入NT驅動的類 C++C++
- 一個隨機數的類c++隨機C++
- C++ 類别範本的寫法C++
- C/C++ Qt TableDelegate 自定義代理元件C++QT元件
- C++ 抽象類快速使用C++抽象
- C++ 大整數類(BigInteger類)實現C++
- http代理使用分類介紹HTTP
- c++模板類的使用,編譯的問題C++編譯
- c++類迴圈依賴的問題C++
- C++中的抽象基類(Abstract Base Class)C++抽象
- C++ Qt開發:QItemDelegate 自定義代理元件C++QT元件
- C++設計模式之Proxy模式(代理模式)C++設計模式
- 使用了Buzz庫的HttpClient類來設定代理HTTPclient
- C++ 類成員函式C++函式
- C++ 類成員指標C++指標
- C++學習 2.5 string類C++
- C++類初學筆記C++筆記