Boolan_c++第3周笔记

一、继承,复合,委托(类与类之间的关系)

1. Composition(复合): A拥有B即为复合

template

class queue{

. . .

protected: 

deque 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(); }

}; 

黑色菱形表示,queue中拥有deque

// 类queue中的的成员c是模板deque类型的,这种情况是复合

%%自己已有deque,客户要求与已有类似,就可以创建queue来使用deque的内容

Boolan_c++第3周笔记_第1张图片

复合关系下的构造和析构

Boolan_c++第3周笔记_第2张图片
右图为内存中关系

1)构造由内而外(比较稳定)

Container的构造函数先调用Component的default构造函数,然后才执行自己。

Container::Container(...): Component ()  { ... 外部自己的初始化 };

// 粗体Component部分可以自己写,让编译器调用哪一个,不写的话直接调用默认

2)析构由外而内(要删除,先剖掉外面一层,再一层层向内部)

Container的析构函数首先执行自己,然后才调用Compent的析构函数。

Container::~Container(...) {... ~Component() };

//先把自己的事情做完,再调用内部!

1)2)中次序编译器可以自动完成。

2. Delegation(委托). Composition by reference(虽然用指针,但是学术界只说by reference)

有一个指针指向另外一个类,空心菱形

class StringRep;

class String {

public:

        String();

        String(const char* s);

        String(const String& s);

        String &operator=(const String& s);

        ~String();

.  .  .  .

private:

        StringRep* rep;   //用指针指向为我实现功能的类,rep为一个指向StringRep类的指针

};

class StringRep()

两个类之间委托,就是用指针相连。

Boolan_c++第3周笔记_第3张图片
string字符串中三个量在共享

3. Inheritance(继承)

1)三种继承方式:

public(比较常用,is a的意思),父类的public和private成员作为派生类的成员时,他们都保持原有的状态,而父类的私有成员仍然是私有的,不能被这个派生的子类访问。

private,父类的public和protected作为私有的,不能被派生的子类访问

protected,父类的所有public和protected都为派生类的protected成员,只能被派生类的成员函数/友元访问,父类的私有成员仍然是私有的。

2)struct和class最本质的一个区别是默认的访问控制:默认的继承访问权限

struct是public,class是private的。

struct A

{char a;};

struct B : A

{char b;};   //此时B是public继承A;如果将struct改成class,B是private继承A的

3)

struct  _List_node_base

{

_List_node_base* _M_next;

_List_node_base* _M_prev;

};

templete

struct _List_node : public _List_node_base      //继承关系

{ _Tp _M_data; };

Boolan_c++第3周笔记_第4张图片
子类指向父类,因为由模板,加T

4)继承关系下的构造和析构

Boolan_c++第3周笔记_第5张图片
右图为在内存中,子类(派生类)中有父类的成分

base class的析构函数必须是虚函数

构造要由内而外,子类的构造函数首先要调用父类的默认构造函数,然后才执行自己

Derived::Derived(...): Base() { ... };

析构要由外而内,Derived的析构函数首先执行自己,然后才调用Base的析构函数

Derived::~Derived(...) {...  ~Base() };


二、虚函数与多态

继承最重要的是和虚函数搭配~~

函数继承的是对函数的调用权

virtual 成员函数;  //虚函数

1.成员函数种类

1)非虚函数(普通函数):不希望子类重新定义(override)它

2)虚函数:希望子类重新定义它,且你对它已有默认定义

3)纯虚函数:希望子类一定要重新定义它,你对它没有默认定义

virtual { } = 0;  // 有virtual和=0    eg,virtual void draw( ) const = 0;

2.虚函数应用(继承搭配虚函数)

Boolan_c++第3周笔记_第6张图片
打开文件问题,用一个父类来写,具体是哪个文件要在子类中通过虚函数来实现/纯虚函数也可以(一定要重新定义),在main中创建一个子类的对象,通过子类对象调用父类函数。OnFileOpen()函数就是Template Method(c++23种设计模式之一)

上图中Application framework,把确定的部分写好,不确定的地方写成虚函数,让子类来定义。

3. 继承+复合关系下的构造和析构

Boolan_c++第3周笔记_第7张图片
上图,父类和子类,子类里面有另外一个类,内存中,如右边图。问题1:构造函数的调用顺序?(写代码测试,父类和复合类要看创建对象的顺序)   下图,子类和父类,父类中有另外component类,内存中结构即右下图,调用构造函数顺序,从内到外

三、委托相关设计

1. 委托+继承

eg,可实现同时打开多个窗口,一个窗口内容变化会影响到另外的窗口

file system文件系统,文件中有目录。。。

如何将他们关联

上述问题解析:容器和类一起用的时候,要在容器中放指针

Boolan_c++第3周笔记_第8张图片
Composite(23个设计模式之一)

class Component

{

        int value;

public:

        Component(int val) { value = val; }

        virtual add(Component*) { }

};

class Composite : public Component

{

        vector c;

public:

        Composite(int val): Component(value) { }

        void add(Component* elem)

        {

            c.push_back(elem);

        }

...

};

class Primitive: public Component

{

public:

        Primitive(int val): Component(val) { } 

};


Prototype

Boolan_c++第3周笔记_第9张图片
在这个图中,下面有下划线的表示静态的,前面有负号表示private,正号(默认不写)表示public;前面#是protected。
Boolan_c++第3周笔记_第10张图片
每个子类有自己的个体,个体中都有一个构造函数将自己挂上去,让上面部分能看到自己;addPrototype(this); this是把自己传进去
Boolan_c++第3周笔记_第11张图片
摘自《Design patterns Explained Simply》

类中声明的静态变量,一定要在类外对其进行定义(分配内存)

你可能感兴趣的:(Boolan_c++第3周笔记)