Object Oriented Programming and Object Oriented Design(面向?qū)ο缶幊毯驮O(shè)計)
本章內(nèi)容:
1 組合與繼承
2 虛函數(shù)與多態(tài)
3 委托相關(guān)設(shè)計
1 組合與繼承
- 在該節(jié)中包含了三種關(guān)系:
(1). Composition(復(fù)合)
(2). Delegation(委托)
(3). Inheritance(繼承)
(1) Composition(復(fù)合)
- 復(fù)合表示
has-a
關(guān)系,例如queue
包含deque
,代碼如下所示:
-
復(fù)合關(guān)系下的構(gòu)造和析構(gòu),下圖中
Container
包含Component
台谊,UML圖和對象結(jié)構(gòu)圖如下所示:
構(gòu)造由內(nèi)而外:
-
Container
的構(gòu)造函數(shù)首先調(diào)用Component
的default
構(gòu)造函數(shù)剔宪,然后再執(zhí)行自己的構(gòu)造函數(shù)拘悦,如下所示:Container::Container(...) : Component() {...}
其中
Component()
是編譯器默認(rèn)添加上去的低零。析構(gòu)由外而內(nèi):
-
Container
的析構(gòu)函數(shù)首先執(zhí)行自己的析構(gòu)函數(shù),然后再調(diào)用Component
的析構(gòu)函數(shù)姥宝,如下所示:Container::~Container(...) {... ~Component(); }
其中
~Component()
是編譯器默認(rèn)添加上去的。
(2) Delegation(委托)
-
委托可以用Composition by reference表示恐疲,其中Composition by reference在這表示指針的意思腊满,UML圖如下所示:
-
經(jīng)典的pImpl(point to implement)或Handle/Body模式,如下代碼所示:
class StringRep; class String { public: String(); String(const char* s); String(const String& s); String& operator=(const String& s); ~String(); ...... private: StringRep* rep; // pImpl }; class StringRep { public: friend class String; StringRep(const char* s); ~StringRep(); private: int count; char* rep; }; String::String() { ... } ......
這個pImpl俗稱“編譯防火墻”培己,其可以用一個指針指向一個類碳蛋,
StringRep
類實(shí)現(xiàn)了具體的方法功能,String
類只調(diào)用StringRep
類的指針來實(shí)現(xiàn)其定義的接口漱凝,如此一來對外接口可以保持不變疮蹦,而具體的實(shí)現(xiàn)部分可以根據(jù)實(shí)際要求來用不同的方式實(shí)現(xiàn),從而達(dá)到了接口和實(shí)現(xiàn)隔離的效果茸炒。
(3) Inheritance(繼承)
-
繼承表示
is-a
關(guān)系愕乎,如下圖表示:
-
繼承關(guān)系下的構(gòu)造和析構(gòu):
構(gòu)造由內(nèi)而外:
-
Derived
的構(gòu)造函數(shù)首先調(diào)用Base
的defaule
構(gòu)造函數(shù)阵苇,然后再執(zhí)行自己的構(gòu)造函數(shù),如下代碼所示:Derived::Derived(...) : Base() { ... }
其中
Base()
是編譯器默認(rèn)添加上去的感论。析構(gòu)由外而內(nèi):
-
Derived
的析構(gòu)函數(shù)首先執(zhí)行自己的構(gòu)造函數(shù)绅项,然后再調(diào)用Base
的析構(gòu)函數(shù),如下代碼所示:Derived::Derived(...) { ... ~Base() }
其中
~Base()
是編譯器默認(rèn)添加上去的比肄。
注意:base class
的destructor
必須是virual
的快耿,否則會造成內(nèi)存泄漏或其他沒有定義的行為。
2 虛函數(shù)與多態(tài)
Inheritance(繼承) with virtual functions(虛函數(shù))
(1).non-virtual
函數(shù):你不希望derived class
重新定義(override
芳绩,覆寫)它掀亥。
(2).virtual
函數(shù):你希望derived class
重新定義(override
,覆寫)它妥色,且你對它已有默認(rèn)定義搪花。
(3).pure virtual
函數(shù):你希望derived class
一定要重新定義(override
,覆寫)它嘹害,你對它沒有默認(rèn)定義撮竿。-
三種
functions
的代碼表示方式如下圖:
-
Inheritance+Composition關(guān)系下的構(gòu)造和析構(gòu)
(1) Derived has a Component & Derived is a Base,UML圖如下所示:
構(gòu)造由內(nèi)而外:
Derived
的構(gòu)造函數(shù)首先調(diào)用Base
的default
構(gòu)造函數(shù)笔呀,然后調(diào)用Component
的構(gòu)造函數(shù)幢踏,最后執(zhí)行自己的構(gòu)造函數(shù)。析構(gòu)由外而內(nèi):
-
Derived
的析構(gòu)函數(shù)首先執(zhí)行自己的構(gòu)造函數(shù)许师,然后調(diào)用Component
的析構(gòu)函數(shù)房蝉,最后調(diào)用Base
的析構(gòu)函數(shù)。(2) Derived is a Base & Base has a Component枯跑,UML圖如下所示:
構(gòu)造由內(nèi)而外:
Derived
的構(gòu)造函數(shù)首先調(diào)用Component
的構(gòu)造函數(shù)惨驶,然后調(diào)用Base
的default
構(gòu)造函數(shù),最后執(zhí)行自己的構(gòu)造函數(shù)敛助。析構(gòu)由外而內(nèi):
Derived
的析構(gòu)函數(shù)首先執(zhí)行自己的構(gòu)造函數(shù)粗卜,然后調(diào)用Base
的析構(gòu)函數(shù),最后調(diào)用Component
的析構(gòu)函數(shù)纳击。
3 委托相關(guān)設(shè)計
Delegation(委托)+Inheritance(繼承)
-
委托+繼承的用法之
Observe
(觀察者)模式续扔,UML圖如下所示:
-
具體代碼示例如下:
class Observer { public: virtual void update(int value) = 0; }; class Subject { private: int m_value; vector<Observer*> m_views; public: void attach(Observer* obs) { m_views.push_back(obs); } void set_val(int value) { m_value = value; notify(); } void notify() { for (int i=0;i<m_views.size();i++) { m_views[i]->update(m_value); } } }; // 繼承觀察者類 class Observer1 : public Observer { private: int m_div; public: Observer1(Subject* model, int div) { model->attach(this); m_div = div; } void update(int v) { ... } }; class Observer2 : public Observer { private: int m_mod; public: Observer2(Subject* model, int mod) { model->attach(this); m_mod= mod; } void update(int v) { ... } }; // 使用詳解 int main(void) { Subject subj; Observer1 o1(&subj, 4); Observer1 o2(&subj, 3); Observer2 o3(&subj, 3); subj.o1(14); }
-
(2) 委托+繼承的用法之
Composite
(組合)模式,UML圖如下所示:
-
具體代碼示例如下:
class Component { private: int value; public: Component(int val) { value = val; } virtual void add(Component*) {} }; class Composite : public Component { private: vector<Component*> c; public: Composite(int val) : Component(val) {} void add(Component* elem) { c.push_back(elem); } ...... }; class Primitive : public Component { public: Primitive(int val) : Component(val) {} };