程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Effective C++:條款38:通過復合塑模出has-a或“根據某物實現出”

Effective C++:條款38:通過復合塑模出has-a或“根據某物實現出”

編輯:C++入門知識

(一)

public繼承是“is-a“的關系,而復合有”has-a“或”根據某物實現出(is-implemented-in-terms-of)“的意思——當復合發生在應用域內的對象之間,表現出has-a關系;當它發生於實現域內則是表示“根據某物實現出”的關系。

應用域部分,相當於你塑造的世界中的某些事物,例如人,汽車等。

後者的對象則是實現細節人工產品(這產品現實世界中是沒有的),像什麼mutex,list,container等等。這些對象是你的軟件的實現領域。

復合:

class Address{...};
class PhoneNumber{...};
class Person{
      ...
private:
      std::string name_;
      Address address_;
      PhoneNumber voiceNumber_;
      PhoneNumber faxNumber_;
};

(二)

實例:set的構造。標准程序庫中有set模板,它“每個元素都耗用三個指針”,是用平衡查找樹實現而成,使它們在查找、插入、刪除元素時保證擁有log(n)的效率。

可能會想到像這樣實現:

讓set繼承stl::list:

template 
class Set : public list{...};   //將list應用於set。錯誤做法。
這種做法是錯誤的!因為:public繼承是is-a關系,父類能做的,子類也一定能做。但set不是一種list,因為對list為真的某些事情對set對象並不為真。例如,list可以內含重復元素,如果30被安插到list兩次,那個list將內含兩個30,如果30被安插到set兩次,set只內含一個30.
所以這兩個classes之間並非is-a關系。不應該是public繼承,正確的做法是,set對象可根據一個list對象實現出來:

template 
class Set {
public:
	bool member(const T& item) const;
	void insert(const T& item);
	void remove(const T& item);
	size_t size() const;
private:
	list rep;
};

template 
bool Set::member(const T& item) const {
	return find(rep.begin(), rep.end(), item) != rep.end();
}

template 
void Set::insert(const T& item) {
	if(!member(item)) rep.push_back(item);
}

template 
void Set::remove(const T& item) {
	typename list::iterator it = find(rep.begin(), rep.end(), item);
	if(it != rep.end()) rep.erase(it);
}

template 
size_t Set::size() const {
	return rep.size();
}


請記住:

(1)復合的意義和public繼承完全不同。

(2)在應用域,復合意味著has-a(有一個)。在實現域,復合意味著is-implemented-in-terms-of(根據某物實現出)。









  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved