1、复合
1.1 何为复合
复合,就相当于 has a ,拥有什么 。这个例子中,是 queue 有 deque
这里写一个queue类,但是在public中可以看到,所使用的函数,是完全利用c,也就是deque的操作函数。比如pop,只是把名字改了。在deque里或许还有很多其他的函数,但是在queue中,只开放了这里的几个。如果声明一个queue类的对象,也只能使用这几个操作函数,且名字的使用与queue一致。 queue是adapter。
1.2 复合后的内存
一步步捋清楚。首先在queue类中,有一个deque类型的对象 c ,那么久来看deque的大小。在deque中,一个无符号整型 4,一个指针的指针还是指针大小 4,和两个Itr类型对象。那么继续看Itr,四个指针(或者指针的指针)大小 4 * 4,一步步返回,queue大小 40.
1.3 复合下的构造和析构
构造函数:由内而外 Container的构造函数先调用Component 的default构造函数,再调用自己的 红色部分先执行,然后再执行自己的。注意红色部分是不用写的,编译器自动调用。 注意是default构造函数。Component可能包含几个构造函数,但是,编译器只会调用默认的。如果需要先调用其他的构造函数,需要写明包含什么参数 析构函数:由外至内 构造函数:由内而外 Container的析构函数先调用自己的析构函数,再调用Component的析构函数。红色部分同样不需要写出来
2 委托
2.1何为委托
如图黄色部分。在String这个Class中,有一个指针私有成员,但这个指针类型却是另一个类Class,相当于,在String中要实现什么功能,把这个功能的实施办法委托给了StringRep。委托也叫Composition by reference
2.2 与复合的不同
复合似乎也是将需要实现的功能"委托"给了别的class,但是两者还是有些区别。
2.2.1 生命周期的不同
在复合中,有了外部,就会有内部,两者同时创建。 在委托中,外部先创建,指针部分需要时创建,不同步
3 继承
3.1 何为继承
黄色部分是语法形式。继承,相当于 is a,是一种东西。右图,_List_node继承_List_node_base。_List_node_base有两个指针型变量,然而在_List_node中,不仅有自己的变量_M_data,还有继承的_List_node_base两个指针型变量。
3.2 继承下的构造和析构
跟组合差不多,一张图。 但是注意右边一句话,父类的析构函数必须是virtual。如果我判断这个类将会成为父类,那么析构就写成virtual。
4 虚函数
4.1 何为虚函数
子承父类,同样继承了父类的函数和变量。继承变量从内存空间上好理解,那么函数从内存上如何理解呢?答案就是不能从内存角度理解。所谓继承父类函数,本质是继承了一种使用权。 继承的函数,有些需要重新定义,有些不需要,而有些需不需要却是强制性的。重新定义父类函数便是虚函数,对于重新定义的强制性,便又分出了几类函数。 非虚函数:不希望derived class重新定义(覆盖 override)它。 **虚函数:**希望子类重新定义,且父类对他已经有默认定义。 纯虚函数:希望子类一定重新定义,且对他无默认定义
4.2 继承+虚函数经典用法–Template Method
这条灰线的流程: 首先,main函数中声明一个CMyDoc类的对象 mydoc,并调用所继承的OnFileOpen函数。在OnFileOpen函数中,执行很多步,来到Serialize函数,这个函数在父类中是纯虚函数,父类无定义,子类一定定义了。此时用到这个函数时,又会回到子类,使用子类的Serialize函数,调用完毕后。最后回到main。这也是经典设计模式之一–Template Method
4.3 继承 + 复合时,构造与析构
两种情况如下: 情况一:一个子类 既继承了一个父类,又组合其他的部分。 弹幕说Base 的构造函数先实现 情况二:一个子类继承了一个父类,然而这个父类组合了其他部分 由图,构造函数由内而外,显然 构造函数顺序:Component part > Base Part >Derived Part。。析构函数反之。
5 三大特性的具体使用
5.1 委托 + 继承 - - 观察者模式
抛出问题:三个窗口,相当于三个不同方式观察的人。如果左边的数据改变,想要右边条状和(薛定谔的)圆柱统计图同时发生改变。如何设计? 如下:
一份数据,即subject类存放数据,委托一个observer类。observer又可以被继承,可以有几个观察者。这几个观察者就可以都使用subject中的数据。 参考这个: 观察者模式
|