继承和派生
基类、派生类
在派生类的各个成员函数中,不能访问基类中的private成员
class 派生类名: public 基类名
{
};
成员函数的覆盖
基类名::成员函数名();
派生类对象的体积(内存空间),等于基类对象的体积,再加上派生类对象自己的成员变量的体积。在派生类对象中,包含着基类对象,而且基类对象的存储位置位于派生类对象新增的成员变量之前。
Question
<string.h>是旧的C 头文件,对应的是基于char*的字符串处理函数;
<string>是包装了std 的C++头文件,对应的是新的string 类(看下文);
<cstring>是对应于旧C 头文件的std 版本。
继承关系和复合关系
继承:“是”关系,逻辑上要求,一个B对象也是一个A对象
复合:“有”关系,一般逻辑上要求,D对象是C对象的固有属性或组成部分
class CPoint {
double x, y;
friend class CCircle; //便于Ccirle类操作其圆心
};
class CCircle {
double r;
CPoint center;
};
小区养狗管理程序。狗只有一个主人,但是一个业主可以有多条狗。不能循环定义。狗、业主。
class CMaster;
class CDog {
CMaster *pm; // 不同狗相同主人的信息一致性,要使用指针
};
class CMaster {
CDog *dogs[10]; // 狗不是主人的固有属性,所以要使用指针。另外,操作狗,只能通过主人,失去了狗类的独立性
};
人狗关系的和谐……
基类/派生类同名成员与protected关键字
基类的private成员: 可以被下列函数访问
- 基类的成员函数
- 基类的友员函数
基类的public成员: 可以被下列函数访问
- 基类的成员函数
- 基类的友员函数
- 派生类的成员函数
- 派生类的友员函数
- 其他的函数
基类的protected成员: 可以被下列函数访问
- 基类的成员函数
- 基类的友员函数
派生类的成员函数可以访问当前对象的基类的保护成员
class Son:public Father { public: void AccessFather() { nProtected = 1; Son f; f.nProtected = 1; // wrong } }
派生类的构造函数
派生类对象包含基类对象,执行派生类构造函数之前,先执行基类的构造函数
构造函数名(形参表): 基类名(基类构造函数实参表)
{
}
FlyBug::FlyBug (int legs, int color, int wings):Bug(legs, color) {
nWings = wings;
}
调用基类构造函数的两种方式
显式方式:
派生类的构造函数中 –> 基类的构造函数提供参数derived::derived(arg_derived-list):base(arg_base-list)
- 隐式方式:
派生类的构造函数中, 省略基类构造函数时
派生类的构造函数, 自动调用基类的默认构造函数
派生类的析构函数被执行时, 执行完派生类的析构函数后, 自动调用基类的析构函数
创建 派生类的对象 时, 执行 派生类的构造函数 之前:
• 调用 基类 的构造函数,初始化派生类对象中从基类继承的成员
• 调用 成员对象类 的构造函数,初始化派生类对象中成员对象
class FlyBug: public Bug {
int nWings;
Skill sk1, sk2;
public:
FlyBug(int legs, int color, int wings);
};
FlyBug::FlyBug( int legs, int color, int wings):
Bug(legs, color), sk1(5), sk2(color) {
nWings = wings; // 可以放在sk1之前吗?nWings(wings)
}
Question
Skill();
Skill(Skill&);
FlyBug(int legs, Skill &sk, int wings); // 顺序比较奇怪,会先初始化sk(VS2013)
public继承的赋值兼容规则
class base { };
class derived : public base { }; // 公有派生
base b;
derived d;
1) 派生类的对象可以赋值给基类对象
b = d;
2) 派生类对象可以初始化基类引用
base &br = d;
3) 派生类对象的地址可以赋值给基类指针
base * pb = &d;
如果派生方式是 private或protected,则上述三条不可行
在声明派生类时,只需要列出它的直接基类,派生类沿着类的层次自动向上继承它的间接基类