首先反思一下第二周作业。我在Rectangle类中对Point类的数据成员进行赋值,而没有为Point写构造函数再通过构造函数初始化Point的成员,这样是不好的。“每个类负责定义各自的接口”,“要想与对象交互必须使用该类的接口(C++ Primer中文第五版 P532)”,这样的准则在原书中是描述基类和派生类的,我觉得同样适用于委托。因此第二周作业中Point和Rectangle应该负责定义各自的接口。
这一周老师举了很多设计模式的例子,我觉得这种方式的确可以使我理解复合,委托和继承,但是距离理解并应用这些设计模式还差得非常远。因此这篇笔记只记录继承相关的内容,设计模式后面还有课,到那时再深入吧。为了理解第三周的课程,我阅读了C++ Primer(中文第五版)的相关内容,看了网易云课堂上面崔毅东老师的C++程序设计入门(上)中关于继承的部分,从这两个来源和本周的课程,我总结了继承中的一些我掌握不好的概念。
派生类与基类之间是一种“is a”的关系,即派生类是一种基类(派生类中的一部分是基类)。基类的所有成员都会被派生类继承,继承的是调用权,即子类可以像父类一样工作,调用父类的成员(函数和数据)。
派生类不继承的函数包括:基类的析构函数,友元函数和赋值运算符。
派生类构造函数必须调用基类的构造函数。在创建派生类对象时会调用基类的构造函数,派生类的实例会按照从基类到派生类的顺序沿着继承链调用所有的基类构造函数。若基类的构造函数没有被显式地调用,则基类的无参构造函数会被调用(如果基类没有无参构造函数,编译器会报错,因此为类写一个=default构造函数是一个好习惯)。如果想用除基类无参构造函数之外的其他构造函数,需要进行显式调用。
在一个继承链中,析构函数的调用顺序与构造函数的调用顺序相反。
多态
广义的多态:不同对象对相同的消息有不同的响应。截至目前,多态表现为重载和重定义。
//重载 class C { int f() {}; int f(int i) {}; };
//重定义class Base{public: int f() {};};class Derived : public Base{public: int f() {};};
重载函数与重定义函数的区别:
重载函数:只在参数上有区别(类型,数量,顺序)。
重定义函数:在基类和派生类中分别定义,同名,同参数(类型,数量,顺序都一致),同返回类型。派生类中的重定义函数会覆盖掉基类中的同名函数。
访问控制(Accessibility)
1.基类中的访问说明符:
private:只能由类内函数访问
public:被任意其他类访问
protected:可被派生类成员(注意,不是派生类对象)访问
2.派生类中的访问说明符:
(1).公有继承
基类成员在派生类中的访问属性不变。
派生类的成员函数可以访问基类的公有成员和受保护成员。
(2).私有继承
基类成员在派生类中的访问属性都变成私有的。
派生类的成员函数可以访问基类的公有成员和受保护成员。
派生类之外的其他函数不可以通过派生类对象访问从基类继承来的任何成员。
(3).受保护继承
基类中的公有成员和受保护成员在派生类中的访问属性都变成受保护的。基类的私有成员仍是私有的。
派生类的成员函数可以访问基类的公有成员和受保护成员。
派生类之外的其他函数不可以通过派生类对象访问从基类继承来的任何成员。
私有继承与受保护继承的区别在于:私有继承中,孙类(派生类的派生类)的成员函数无法访问子类从父类继承来的所有成员;而受保护继承中,孙类(派生类的派生类)的成员函数可以访问子类从父类继承来的公有成员和受保护成员,因为它们在子类中都是受保护的。
抽象基类与虚函数
继承链越往上就越抽象,越往下越具体。因为过于抽象而无法实例化(为之创建对象)的类就是抽象类。含有纯虚函数的基类就是抽象基类。