面向对象(类和类之间的关系)--继承(虚函数的调用时的隐藏this)、复合、委托
1、复合Composition(has-a关系,一个类中包含另一个类的对象)
构造时,由内到外,析构时,由外到内。
Adapter设计模式,queue是deque的adapter。因为deque完全含有queue的所有功能,queue就是在deque上面设计的。
1 template<class T,class Sequence = deque<T>> 2 class queue{ 3 ... 4 protected: 5 Sequence c;//复合关系 6 public: 7 bool empty() const {return c.empty();} 8 size_type size() const {return c.size();} 9 reference front() {return c.front();} 10 reference back(){ return c.back();} 11 void push(const value_type& x) {c.push_back(x);} 12 void pop () { c.pop_front();} 13 }; 14 template<class T> //同上面相同功能,不同形式 15 class queue{ 16 ... 17 protected: 18 deque<T> c; 19 ... 20 };
2、委托Delegation(一个类中含有另一类的指针)
Handke/Body(pImpl) ------>扩展出引用计数和写时拷贝
class StringRep; class String{ public: String(); String(const char*s); String(const String&s); String& operator=(const String& s); ~String(); ... private: StringRep *rep; //有一个handle,body有很好的可扩展性。 };
3、继承Inheritance(is-a关系,子类继承自父类)
构造时,由内到外,析构时,由外到内。
struct _List_node_base{ _List_node_base* _M_next ; _List_node_base* _M_prev; }; template<typename _Tp> struct _List_node : public _List_node_base{ _Tp _M_data; };
①non-virtual 函数:不希望子类重新定义它
②virtual函数:可以有默认定义,但希望子类去重新定义它。(有virtual的类,析构函数一定要设计成virtual)
③pure virtual函数:希望子类一定要重新定义它。(含有纯虚函数的类不能直接生成对象)
4、Template Method(父类的成员函数实现中含有一个虚函数,这个虚函数由子类去实现)
调用父类的成员函数时传入一个隐藏的this(子类的this指针),由this去调用虚函数,则调用的是子类的虚函数。
5、继承并且复合时 Inheritance+Composition(构造时:先构造父类再构造复合类,析构时:先析构复合类再析构父类)
#include<iostream> class A{ private : int a ; public : A(){std::cout << "A is start" << std::endl;} ~A(){std::cout << "A is finsh \n";} }; class B{ private: int b; public: B(){std::cout << "b is start\n";} ~B(){std::cout << "b is finsh \n";} }; class C : public A{ private: B ins ; public: C(){std::cout << "c is start \n";} ~C(){std::cout << "c is finsh \n";} }; int main(){ C c ; return 0; }
6、继承加委托 Inheritance+ Delegation
①观察者模式Observer(Observer去观察Subject,当Subject发生改变时,用notify调用update去通知Observer,update由观察者自己实现。)
以ppt的编写为例:ppt的内容改变后,其左边的缩略图也会被改变,ppt的内容为Subject,缩略图为Observer。
class Observer { public: virtual void update(Subject* sub,int value) = 0; } class A : public Observer { void update(Subject* sub, int value){ .... } } class B : public Observer { void update(Subject* sub, int value){ .... } } 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; motify(); } void notify() { for(int i = 0; i < m_views.size();++i) m_views[i]->update(this,m_value); } }
②Composite模式(右边子类中含有父类的多个指针,这多个指针既可以指向左边的子类,也可以指向右面的子类)
以文件系统为例:左边的子类是文件类,右边的子类是目录类,目录中可以添加一个目录或文件,而文件中不能添加任何目录或文件。在这里父类的add函数不能设置为pure virtual,因为pure virtual必须要被子类实现。
1 class Component{ 2 private: 3 int value; 4 public: 5 Component(int val) : value(val){} 6 virtual void add (Component*) {} 7 }; 8 class Primitive : public Component { 9 public: 10 Primitive(int value) ; Component(val){} 11 }; 12 class Composite : public Component{ 13 private: 14 std::vector<Component* > c ; 15 public: 16 Composite(int val):Component(val){} 17 void add(Component* elem){ //这个elem可以是左边类的实例,也可以是右边类的实例 18 c.push_back(elem); 19 } 20 }
7、动态绑定(必须满足:通过指针调用,指针向上转型,调用虚函数)。
(*(this->vptr)[n])(this)