C++ 学习笔记 4

C++学习笔记4

面向对象,类与类之间的关系

继承inheritance、复合composition与委托delegation

复合(组合)composition,表示has-a

其实就是构建类的时候放进去一个其他类的对象啦。进而就可以使用这个对象的函数来实现自己想要的功能。

比如queue是用deque实现的,只开放了一部分功能。这叫做Adapter(适配器)。

复合关系下的构造和析构

构造由内向外,从被拥有者构造起,具体解释是:Container的构造函数首先调用Component的default构造函数,然后才执行自己。

析构由外而内,首先执行自己,再调用component的析构函数,

委托delegation,用引用来复合

有一个指针指向另外一个对象。这个对象未必存在,在需要调用时再使用。用指针相连。

二者寿命不一致。在复合中是共存亡,在委托是需要再创建。

pimpl( pointer to implementation)

一个类实现函数接口,并用一个指针指向具体实现的类。或称handle / body.

可以在保证接口不变动的情况下,改动底层实现,还不会影响用户的使用。

用于共享数据的实现

可以有计数变量,指向同一个数据。但注意修改时不能改变别人的数据,需要提供一个副本来修改。

继承inheritance,表示is-a

语法,使用 :

struct _List_node : public _List_node_base{
    _Tp _M_data;
}
  • struct可以视为与class一样,非常类似

  • 三个作用范围关键字都可以用于继承,因此继承有三种

    • public才是is-a 的关系
  • 父类所拥有的成员变量是被继承下来的。即子类也有同样的成员变量。进一步到虚函数的应用。

构造与析构

子类的对象里有父类的成分(part)在里面。

构造由内而外,子类先调用父类的default构造函数,然后才执行自己的ctor。

析构由外而内,先执行自己的析构函数,再调用父类的析构函数。

父类的dtor必须是虚函数virtual,否则会出现未定义行为ub。

虚函数

三种成员函数

non-virtual函数:子类不应该重新定义(override,覆写)这个函数。

virtual函数:子类可以重新定义,但是是有默认的定义的。

纯虚pure virtual函数:子类必须重新定义。且没有默认定义。

class Shape{
    public:
    int ID() const;//non-virtual
    virtual void error(const std::string& msg);//impure virtual
    virtual void draw( )const = 0;//pure virtual
}

template method模板函数

指一些函数里,所调用的部分函数只设计好位置和接口,具体实现由后续具体完成。

继承+复合关系下的构造与析构

有如下两种情况:

image-20220111234926138

构造谁先谁后?

第一种,通过如下代码来体现。

#include <iostream>
using namespace std;

class Base{
public:
    Base(){
        cout<<"Base here"<<endl;
    }
};

class Component{
public:
    Component(){
        cout<<"Component here"<<endl;
    }
};

class Derived : public Base{
public:
    Derived(){
        cout<<"Derived here"<<endl;
    }
private:
    Component c;
};

int main() {
    Derived d;
    return 0;
}

//output

//Base here
//Component here
//Derived here

//Process finished with exit code 0

可知是先执行inheritance,再compont

第二种,先component,再inheritance,对代码稍作改动即可。

委托+继承 composite组合模式(部分整体模式)

特征

  • 整体的结构应该是一棵树,
  • 所有的组件应该有一个共同的父类(有共同的本质),
  • 这个父类使得组件中的共同的本质可以提取出来(有了共同语言(父类)),进行互融

图例

image-20220112220032662

image-20220112220055500

组成与功能

primitive
  • 基本的,个体的;或者称为原语(不太合适),意思就是一种不能包含component的子类。
  • 比如文件,
Composite
  • 复合物,组合物。是一个容器,可以容纳primitive和composite自己
  • 如果给primitive和composite找一个共同语言及父类,就可以解决了。
  • 即容纳的对象不写死,可以是composite也可以是primitive。
  • 容纳的对象要写成指针。放对象进去,两者毕竟不一样,大小什么的都不一样。
  • 拥有add函数,可以加进来component。参数也是component就可以。
Component
  • 是共同的父类,“共同语言”
  • 需要定义一个无动作的add函数,是虚函数。不是纯虚函数,因为primitive不能定义add函数。

prototype原型模式

image-20220112222447015

设计者还不知道将来的class会叫什么名字。将来的class创建的东西可以被框架所看到,就可以了,

子类自己创造自己,创造一个static的对象。这个原型可以被父类看得到。因此把原型放到父类的一个数组空间中,可以被父类访问。

构造函数写为private。

父类提供一个addPrototype函数,即把指针放到拥有的容器中。然后对子类调用这个函数,就可以提供给父类。

子类还需要准备一个clone函数,返回new一个子类对象。父类通过他可以访问的数组,调用这个clone函数,就可以做出一个副本。

posted @ 2022-01-12 22:39  biiNG#  阅读(36)  评论(0编辑  收藏  举报