1. 程式人生 > >c++中的繼承、聚合、關聯和組合

c++中的繼承、聚合、關聯和組合

一、繼承、關聯和組合

繼承和組合是兩個完全不同的概念
繼承,表達的是“is-a”的關係,兩者之間是一種上下級的關係,比如,我們說“human is a animal“(人是動物的一種,換句話說,動物是人的上級),要表達這種關係,就可以使用繼承




1 2 3 4 calss animal {}; class human : public animal  // 繼承 {};


而組合和聚合,則是表達兩個平等物件之間整體和區域性的關係,而因為這種關係的緊密性的不同,而又分為了組合和聚合。組合表達的是“contain-a”的關係,整體和區域性擁有相同的生命週期,換句話說,如果整體物件不存在了,那麼區域性物件也會消亡。

在C++中,我們通常在整體類中加入一個區域性類的物件作為其成員,來表達這種組合關係(整體物件建立的同時,也會建立區域性物件,而整體物件消失了,區域性物件也會消失),比如,我們說“human conains a head”(人有一個腦袋,人活著,腦袋也活著,如果人死了,腦袋也就是了),




1 2 3 4 5 6 7 class head {}; calss human { private: head h;  // 資料成員物件表示的組合關係 }


聚合同樣表的是整體和區域性的關係,但是這種關係要鬆散得多,它表達的是一種“has-a”的關係,整體和區域性擁有各自的生命週期,兩者可以單獨存在,相互獨立,並不像組合一樣兩者相互依存,但兩者也可以聚合在一起,形成一個新的型別。比如,我們說“human has a computer”(人有一臺電腦,電腦和人都是各自獨立的,而兩者聚合在一起,就成了“有電腦的人”),

在C++中,我們通常在整體類中加入指向區域性類的指標,來表達這種“聚合”關係(整體物件建立的時候,不一定有區域性物件,可能已經建立,也可以還沒有,而整體物件消失了,區域性物件還可以繼續存在,也可能消失,想象一下電腦和人的關係,生不帶來,死不帶去)。




1 2 3 4 5 6 7 8 calss computer {}; class human { /// ... private: computer* pCom; // 指標表示的聚合關係 };


總結起來,繼承表達的是一種上下級的關係(is-a),聚合表達的是一種鬆散的整體和區域性的關係(has-a),而組合表達的是一種緊密的整體區域性關係(contain-a)

另外:

class A
{
private:
B* p_b;
}

A::A()
{
p_b=new B;
}
A::~A()
{
delete p_b;
}

A與B的關係是組合。雖然是用指標表示的,依然是組合關係。

到底是組合還是聚合,其實現形式(用成員還是指標)不是判斷標準,兩者生命週期的差異,才是判斷標準。兩者生命週期相同的,是組合,比如成員變數,你這裡用指標的實現,而生命週期不同的,才是聚合。二、關聯和聚合

關聯和聚合的區別主要在語義上,關聯的兩個物件之間一般是平等的,例如你是我的朋友,聚合則一般不是平等的,例如一個公司包含了很多員工,其實現上是差不多的。

聚合和組合的區別則在語義和實現上都有差別,組合的
兩個物件之間其生命期有很大的關聯,被組合的物件是在組合物件建立的同時或者建立之後建立,在組合物件銷燬之前銷燬。一般來說被組合物件不能脫離組合物件獨立存在,而且也只能屬於一個組合物件,例如一個文件的版本,必須依賴於文件的存在,也只能屬於一個文件。

聚合則不一樣,被聚合的物件可以屬於多個聚合物件,例如一個員工可能可以屬於多個公司。

我想舉個通俗的例子。
你和你的心臟之間是composition關係(心臟只屬於自己)
你和你買的書之間是aggregation關係(書可能是別人的)
你和你的朋友之間是association關係