c++中的繼承、聚合、關聯和組合
一、繼承、關聯和組合
繼承和組合是兩個完全不同的概念
繼承,表達的是“is-a”的關係,兩者之間是一種上下級的關係,比如,我們說“human is a animal“(人是動物的一種,換句話說,動物是人的上級),要表達這種關係,就可以使用繼承
1 2 3 4 |
calss animal
{};
class
human : public
animal // 繼承
{};
|
而組合和聚合,則是表達兩個平等物件之間整體和區域性的關係,而因為這種關係的緊密性的不同,而又分為了組合和聚合。組合表達的是“contain-a”的關係,整體和區域性擁有相同的生命週期,換句話說,如果整體物件不存在了,那麼區域性物件也會消亡。
1 2 3 4 5 6 7 |
class
head
{};
calss human
{
private :
head h;
// 資料成員物件表示的組合關係
}
|
聚合同樣表的是整體和區域性的關係,但是這種關係要鬆散得多,它表達的是一種“has-a”的關係,整體和區域性擁有各自的生命週期,兩者可以單獨存在,相互獨立,並不像組合一樣兩者相互依存,但兩者也可以聚合在一起,形成一個新的型別。比如,我們說“human has a computer”(人有一臺電腦,電腦和人都是各自獨立的,而兩者聚合在一起,就成了“有電腦的人”),
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關係