(一)
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這種做法是錯誤的!因為:public繼承是is-a關系,父類能做的,子類也一定能做。但set不是一種list,因為對list為真的某些事情對set對象並不為真。例如,list可以內含重復元素,如果30被安插到listclass Set : public list {...}; //將list應用於set。錯誤做法。
templateclass 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(根據某物實現出)。