通過分層來體現 有乙個 或 用 來實現

2021-04-12 18:22:32 字數 2376 閱讀 6673

使某個類的物件成為另乙個類的資料成員,從而實現將乙個類構築在另乙個類之上,這一過程稱為 "分層"(layering)。例如:

class address ;           // 某人居住之處

class phonenumber ;

class person ;

本例中,person類被認為是置於string,address和phonenumber類的上層,因為它包含那些型別的資料成員。"分層" 這一術語有很多同義詞,它也常被稱為:構成(composition),包含(containment)或嵌入(embedding)。

條款35解釋了公有繼承的含義是 "是乙個"。對應地,分層的含義是 "有乙個" 或 "用...來實現"。

上面的person類展示了 "有乙個" 的關係。乙個person物件 "有乙個" 名字,位址,**號碼和傳真號碼。你不能說,乙個人 "是乙個" 名字或乙個人 "是乙個" 位址;你得說,乙個人 "有乙個" 名字, "有乙個" 位址,等等。大多數人對區分這些沒什麼困難,所以混淆 "是乙個" 和 "有乙個" 的情況相對來說比較少見。

稍微有點麻煩的是區分 "是乙個" 和 "用...來實現"。例如,假設需要乙個類模板,用來表示任意物件的集合,並且集合中沒有重複元素。程式設計中,重用(reuse)是再好不過的一件事了,而且你也許已經讀過條款49中關於c++標準庫的總體介紹,那麼,你的第一反應一定是想採用標準庫中的set模板。是啊,既然可以使用別人所寫的東西,為什麼還要再去寫乙個新的模板呢?

但是,深入研究set的幫助文件後,你會發現,set的下述限制將不能滿足你的程式要求:set要求包含在它內部的元素必須是完全有序的,即,對set中的任兩個元素a和b來說,一定可以確定:要麼a當然,重用還是件好事。作為資料結構專家,你知道,在實現集合的眾多選擇中,乙個最簡單的辦法是採用鍊錶。你一定猜到了什麼。對,標準庫中正有這麼乙個list模板(用來產生鍊錶類)!所以可以重用它。

具體來說,你決定讓自己的set模板從list繼承。即,set將從list繼承。因為,在你的實現中,set物件實際上將是list物件。於是你這樣宣告set模板:

// set中錯誤地使用了list

template

class set: public list;

至此,一切好象都很正確,但實際上錯誤不小。正如條款35所說明的,如果d "是乙個" b,對b成立的所有事實對d也成立。但是,list物件可以包含重複元素,所以如果3051這個值被增加到list中兩次,list中將包含3051的兩個拷貝。相反,set不可以包含重複元素,所以如果3051被增加到set中兩次,set中將只包含這個值的乙個拷貝。於是,說乙個set "是乙個" list就是彌天大謊,因為如上所述,有一些在list物件中成立的事實在set物件中不成立。

因為這兩個類的關係並非 "是乙個",所以用公有繼承來表示它們的關係就是乙個錯誤。正確的方法是讓set物件 "用list物件來實現":

// set中使用list的正確方法

template

class set ;

set的成員函式可以利用list以及標準庫其它部分所提供的大量功能,所以,實現**既不難寫也很易讀:

template

bool set::member(const t& item) const

template

void set::insert(const t& item)

template

void set::remove(const t& item)

template

int set::cardinality() const

這些函式很簡單,所以很自然地想到將它們作為內聯函式;但在做最後決定前,還是回顧一下條款33所做的討論。(上面的**中,find, begin, end, push_back等函式是標準庫基本框架的一部分,它們可用來對list這樣的容器模板進行操作。標準庫框架的總體介紹參見條款49和m35。)

值得指出的是,set類的介面沒有做到完整並且最小(參見條款18)。從完整性上來說,它最大的遺漏在於不能對set中的內容進行迴圈,而這一功能對很多程式來說是必需的(標準庫中的所有成員都提供了這一功能,包括set)。set的另乙個缺陷是沒有遵循標準庫所採用的容器類常規(見條款49和m35),從而造成使用set時更難以利用庫中其它的部分。

set的介面儘管有這些瑕疵,但下面這一點不能被掩蓋:set在理解它和list的關係上,具有無可辯駁的正確性。這種關係並非 "是乙個"(雖然初看會以為是),而是 "用...來實現",通過分層來實現這種關係是類的設計者應該感到自豪的。

順便說一句,當通過分層使兩個類產生聯絡時,實際上在兩個類之間建立了編譯時的依賴關係。關於為什麼要考慮到這一點以及如何減少這方面的麻煩,參見條款34。

C 擴充套件乙個現有類

對乙個現有的類進行方法的擴充套件 using system namespace purecsharptest public static class rubbishextensions public static void hello this rubbish rubbish class progr...

c 的體現多型的乙個簡單應用

本 的實現的功能是計算正方形和矩形的面積,所以先建立了乙個抽象的基類base sharp,主要是用於宣告面積的列印方法和面積的計算方法。然後宣告建立了矩形類rectangle和正方形類square,都對基類做了繼承,並且分別對基類中的純虛函式做了實現。test.cpp 定義控制台應用程式的入口點。i...

排序 排序乙個棧(通過乙個輔助棧)

問題描述 現有乙個棧,包含一些整型的元素,現需要將此棧從頂到底按從大到小的順序排列 只允許申請乙個新棧 演算法實現 public void sortstackbystack stackstack help.push cur while help.isempty 演算法解析 1.申請乙個新棧,通過這兩...