组合与继承

本文介绍了C++中三种重要的编程关系:继承、复合和委托。复合通过has-a关系建立对象间的关联,构造由内而外,析构由外而内。委托允许在任何时候将任务转交给其他对象,如String类的pImpl设计模式。继承则实现了is-a关系,配合虚函数实现多态,构造和析构同样遵循特定顺序。
摘要由CSDN通过智能技术生成

主要有三种关系:继承、复合和委托。

1.复合 composition has-a

template <class T, class Sequence = deque<T>>
class queue
{
    ...
    protected:
        Sequence c;//底层容器
    ...
};

上述代码可以写成下图,便于理解

Adapter设计模式:将deque改造成queue

template <class T>
class queue
{
    ...
    protected:
        deque<T> c;//底层容器
    public:
    // 以下完全利用c 的操作函數完成
        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(); }
};

黑色菱形:黑色表示有内容,菱形一端是容器

两层composition,如下图

 composition关系下的构造和析构:

  • 构造由内而外:Container 的構造函數首先調用Component 的default 構造函數,
    然後才執行自己。(如果默认构造函数不符合要求,需要自己写)
    Container::Container(...): Component(){...};
  • 析构由外而内:Container 的析構函數首先執行自己,然後才調用Component 的
    析構函數。
    Container::~Container(...){...~Component()};

2.委托delegation (composition by reference 指针)

在任何时间点都可以将任务委托给对方。

composition: 生命一起出现;delegation:生命可能不同步  

 例:白色空心表示指针

// file 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
};
// file String.cpp
#include "String.hpp"
namespace {
class StringRep {
friend class String;
    StringRep(const char* s);
    ~StringRep();
    int count;
    char* rep;
};
}
String::String(){ ... }
...

pImpl设计模式:pointer to implementation,handle/body

将指针指向外部实现类

好处:指针可以灵活指向任何实现类,客户端保持不变

例:reference counting,三个字符串共享一个hello,节省空间

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

三种类型继承:public private protected,其中public最常用

上述例子是父类的数据被继承,继承最有价值的部分其实是与虚函数搭配

继承关系下的构造与析构

 

  • 構造由內而外:Derived 的構造函數首先調用Base 的default 構造函數,然後才執行自己。
Derived::Derived(...): Base(){...};
  • 析構由外而內:Derived 的析構函數首先執行自己,然後才調用Base 的析構函數。
Derived::~Derived(...){...~Base()};

注:父类的析构函数必须是虚函数,否则会出现undefined behavior

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值