C++面向对象设计

2018-01-09  本文已影响10人  leon4ever

组合、委托、继承

一、composition(组合)has-a

1 组合关系(Adapter 设计模式)

关系:


组合关系.jpg

利用deque功能实现所有queue功能

template <class T>
class queue{
protected:
    deque<T> c; //deque 是两端可进出,queue是末端进,前端出 
public:
    bool empty() const{ return c.empty;}
    size_type size() const{ return c.size();}
    reference front() { return c.front(); }
    reference back() { return c.back(); }
    void push(const value_type& x) { c.push_back(x); }
    void pop() { c.pop_front(); }
};

2 构造与析构

构造由内而外:
container的构造函数先调用component的默认构造函数,再执行自己
如果默认构造函数不符合要求,需自己在外部构造函数写明调用哪个内部构造函数
析构由外而内:
container的析构函数先执行自己,再调用component的析构函数

二、delegation(委托) : composition by reference

以handle/body(Pimpl)设计模式为例
关系图:
存指向另一个对象的指针,composition by reference


委托示意.jpg
委托关系.jpg
// handle String.hpp
class StringRep;
class String {
public:
    String();
    String(const char* s);
    String(const String& s);
    String &operator=(const String& s);
    ~String();
    . . . .
private:
    StringRep* rep; // pimpl
};

//body String.cpp
#include "String.hpp"
namespace {
class StringRep {
friend class String;
    StringRep(const char* s);
    ~StringRep();
    int count;
    char* rep;
};
}

继承(is-a)

1 举例

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;    
};

2 构造与析构

继承关系.jpg

构造函数由内而外,析构函数由外而内;
derived的构造函数先调用base的默认构造函数,再执行自己
derived的析构函数先执行自己,再调用base的析构函数
base的析构函数必须为virtual,否则可能出现只调用基类析构函数,而未调用派生类析构函数

虚函数与多态

一、虚函数

函数的继承,继承的是调用权
非虚函数:不希望子类重新定义(override 复写)它
虚函数:希望子类重新定义(override 复写)它
纯虚函数:希望子类一定要重新定义它,你对它无定义

class Shape {
public:
    virtual void draw( ) const = 0;  //纯虚函数 
    virtual void error(const std::string& msg); //虚函数 
    int objectID( ) const;  //非虚函数 
    ...
};
class Rectangle: public Shape { ... };
class Ellipse: public Shape { ... };

二、以开文件为例

设计模式 Template Method (MFC即为典型的 Application framework)
共有部分在设计父类时事先实现;其他无法决定其定义的(如本例中如何读文件内容)
Serialize声明为虚函数,使其延缓到子类再重新定义,决定其具体的实现。


子类对象调用父类函数流程.jpg

上述过程模拟代码:

#include <iostream>
using namespace std;
class CDocument{
public:
    void OnFileOpen(){
        cout << "dialog..." << endl;
        cout << "check file status..." << endl;
        cout << "open file..." << endl;
        Serialize();
        cout << "close file..." << endl;
        cout << "update all views..." << endl;
    }
    virtual void Serialize(){};
}; 

class CMyDoc : public CDocument{
public:
    virtual void Serialize(){
        //只有应用程序自身知道如何读取自己的文件
        cout<< "CMyDoc::Serialize"<<endl; 
    }
};

int main(){
    CMydoc myDoc;
    myDoc.OnFileOpen();
}
上一篇下一篇

猜你喜欢

热点阅读