面向对象编程和设计 (Boolan)
Object Oriented Programming and Object Oriented Design(面向对象编程和设计)
本章内容:
1 组合与继承
2 虚函数与多态
3 委托相关设计
1 组合与继承
- 在该节中包含了三种关系:
(1). Composition(复合)
(2). Delegation(委托)
(3). Inheritance(继承)
(1) Composition(复合)
- 复合表示
has-a
关系,例如queue
包含deque
,代码如下所示:
-
复合关系下的构造和析构,下图中
UML和对象结构图Container
包含Component
,UML图和对象结构图如下所示:
-
构造由内而外:
-
Container
的构造函数首先调用Component
的default
构造函数,然后再执行自己的构造函数,如下所示:Container::Container(...) : Component() {...}
-
其中
Component()
是编译器默认添加上去的。 -
析构由外而内:
-
Container
的析构函数首先执行自己的析构函数,然后再调用Component
的析构函数,如下所示:Container::~Container(...) {... ~Component(); }
-
其中
~Component()
是编译器默认添加上去的。
(2) Delegation(委托)
-
委托可以用Composition by reference表示,其中Composition by reference在这表示指针的意思,UML图如下所示:
Delegation(委托) -
经典的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
类实现了具体的方法功能,String
类只调用StringRep
类的指针来实现其定义的接口,如此一来对外接口可以保持不变,而具体的实现部分可以根据实际要求来用不同的方式实现,从而达到了接口和实现隔离的效果。
(3) Inheritance(继承)
-
继承表示
is-a关系图is-a
关系,如下图表示:
-
继承关系下的构造和析构:
UML和对象结构图 -
构造由内而外:
-
Derived
的构造函数首先调用Base
的defaule
构造函数,然后再执行自己的构造函数,如下代码所示:Derived::Derived(...) : Base() { ... }
-
其中
Base()
是编译器默认添加上去的。 -
析构由外而内:
-
Derived
的析构函数首先执行自己的构造函数,然后再调用Base
的析构函数,如下代码所示:Derived::Derived(...) { ... ~Base() }
-
其中
~Base()
是编译器默认添加上去的。
注意:base class
的destructor
必须是virual
的,否则会造成内存泄漏或其他没有定义的行为。
2 虚函数与多态
-
Inheritance(继承) with virtual functions(虚函数)
(1).non-virtual
函数:你不希望derived class
重新定义(override
,覆写)它。
(2).virtual
函数:你希望derived class
重新定义(override
,覆写)它,且你对它已有默认定义。
(3).pure virtual
函数:你希望derived class
一定要重新定义(override
,覆写)它,你对它没有默认定义。 -
三种
virtual functions虚函数functions
的代码表示方式如下图:
-
Inheritance+Composition关系下的构造和析构
(1) Derived has a Component & Derived is a Base,UML图如下所示:
UML图 -
构造由内而外:
-
Derived
的构造函数首先调用Base
的default
构造函数,然后调用Component
的构造函数,最后执行自己的构造函数。 -
析构由外而内:
-
Derived
的析构函数首先执行自己的构造函数,然后调用Component
的析构函数,最后调用Base
的析构函数。(2) Derived is a Base & Base has a Component,UML图如下所示:
UML图 -
构造由内而外:
-
Derived
的构造函数首先调用Component
的构造函数,然后调用Base
的default
构造函数,最后执行自己的构造函数。 -
析构由外而内:
-
Derived
的析构函数首先执行自己的构造函数,然后调用Base
的析构函数,最后调用Component
的析构函数。
3 委托相关设计
-
Delegation(委托)+Inheritance(继承)
-
委托+继承的用法之
观察者模式UML图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) 委托+继承的用法之
组合模式UML图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) {} };