1、composition(复合)
template<class T, class Sequence = deque<T>> class stack { friend bool operator==<> (const stack &, const stack&); friend bool operator< <> (const stack&, const stack&); public: typedef typename Sequence::value_type value_type; typedef typename Sequence::size_type size_type; typedef typename Sequence::reference reference; typedef typename Sequence::const_reference const_reference; protected: Sequence c; //底层容器 deque<T>,以下操作完全由底层容器代为操作 public: bool empty() const { return c.empty(); } size_type size() const { return c.size(); } reference top() const { return c.back(); } void push(const value_type&x) { c.push_back(x); } void pop(){ c.pop_back(); } };
画图表示
复合关系下的构造和析构:
stack的构造函数首先会调用deque的构造函数,然后再执行自己的构造函数。析构则相反。下面是个测试程序,man中含有一个person
class person { public: person() { cout << "person的默认构造函数" << endl; } person(string name, int age) :m_name(name), m_age(age) { cout << "person的有参构造函数" << endl; } ~person() { cout << "person的析构函数" << endl; } private: string m_name; int m_age; }; class man { public: man() { cout << "man的默认构造函数" << endl; } man(string name, int age) :p(name, age) { cout << "man的有参构造" << endl; } ~man() { cout << "man的析构函数" << endl; } private: person p; //man class中有person }; void test01() { man haha("liming", 12); }
打印结果:
2、delegation(委托)
delegation和composition很像。A类的内部拥有的是B类的指针,对B类做修改并不影响A类的接口。
一个测试程序
class person { public: person() { cout << "person的默认构造函数" << endl; } person(string name, int age) :m_name(name), m_age(age) { cout << "person的有参构造函数" << endl; } void showinfo() const { cout << "name:" << m_name << "," << "age:" << m_age << endl; cout << "这是我做的修改" << endl; } ~person() { cout << "person的析构函数" << endl; } private: string m_name; int m_age; }; class man { public: man() { p = new person; cout << "man的默认构造函数" << endl; } man(string name, int age) { p = new person(name, age); cout << "man的有参构造" << endl; } void showname() const { p->showinfo(); } ~man() { if (p != NULL) { delete p; p = NULL; } cout << "man的析构函数" << endl; } private: person *p; }; void test01() { //man haha; mam haha("liming",12); haha.showname(); }
画图表示:
3、继承
子类内部拥有父类的成分。构造的时候由内到外,析构由外到内。子类拥有父类的数据,拥有父类的函数调用权。而父类中函数可以分为三类函数:1、non-virtual函数:不希望子类可以重写他;2、virtaul函数,子类可以重写,父类有默认的定义;3、pure virtual 子类必须重写,父类没有定义。
class animal { virtual void speak() = 0; //纯虚函数,子类必须重写 virtual void eat() //虚函数,子类可以重写 { cout << "吃肉" << endl; } void run() { cout << "走路" << endl; } }; class cat :public animal {}; class sheep :public animal {};
这里衍生出的一个经典的设计模式——template method
把不变的部分先写好,动态变化的部分留给编写应用程序的人来编写。
1 //相当于library 2 class CDocument 3 { 4 public: 5 void onFileOpen() 6 { 7 cout << "dialog..." << endl; 8 cout << "check file..." << endl; 9 cout << "open file.." << endl; 10 Serialize();//动态变化的部分 11 cout << "close file..." << endl; 12 } 13 virtual ~CDocument(){} protected: 14 virtual void Serialize()=0; 15 }; 16 //application 17 class CMyDoc:public CDocument 18 { 19 public: 20 void Serialize() //子类重写 21 { 22 cout << "CMyDoc::serialize..." << endl; 23 } 24 }; 25 int main() 26 { 27 CMyDoc mydoc; 28 mydoc.onFileOpen(); //子类对象调用父类函数 29 }