继承
一、什么是继承
1.1继承的概念
继承(inheritance)是面向对象软件技术当中的一个概念。这种技术使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用。它允许程序员在保持原有类(基类)特性的基础上进行扩展,增加功能,产生的新类叫做派生类,继承呈现了面向对象软件技术的层次结构, 体现了由简单到复杂的认知过程,继承属于类设计层次的复用。
1.2继承的定义
1.1.1格式
基类则称父类,派生类也称子类
1.1.2继承方式
这里可以看出,继承方式就是我们所说的访问限定符,意思基本相同。
1.1.3继承基类成员访问方式的变化
总结:
1.无论何种继承方式,父类的私有成员在子类中都不可见。
2.父类其他成员(除私有成员外)在子类的访问方式 == Min(成员在父类类的访问限定符,继承方式),public > protected > private。
3.protected成员无法在类外直接访问,到可以在子类访问。
4.class默认的继承方式是private,struct默认的继承方式是public。
二、继承的相关操作
2.1基类与派生类对象的赋值
首先我们定义一个父类(footballer)和一个子类(people)
class footballer{
public:
string _name;
int _age;
};
class people:public footballer{
public:
string _sex;
};
1.子类对象可以赋值给父类对象/指针/引用(切片)
people A;
footballer B = A;
footballer *C = &A;
footballer &D = A;
2.父类对象不能赋值给子类对象
footballer A;
people B = A; //错误,不能赋值
3.基类的指针可以通过强制类型转换赋值给派生类的指针
footballer A;
people *B = (people*)&A;
这样转换虽然可以,但是会造成访问越界的问题,所有尽量不使用。
2.2作用域
1.继承体系中,子类和父类都有自己独有的作用域
2.子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定义,在子类成员函数中,可以使用基类::基类成员显示访问
3. 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。
三、派生类的默认成员函数
作为一个类,6个默认成员函数是必不可少的
3.1构造函数与析构函数
1.派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。
2.继承自父类的成员必须调用父类构造完成初始化,不能直接在子类构造中进行初始化。
3. 派生类对象初始化先调用基类构造再调派生类构造
4. 派生类对象析构清理先调用派生类析构再调基类的析构。
3.2拷贝构造与赋值运算符重载
1.没有显示定义子类的拷贝构造,执行子类拷贝对象时,子类会自动调用父类的拷贝构造
2.显示定义子类的拷贝构造,执行子类拷贝对象时,子类会自动调用父类的构造函数
3.子类对象赋值过程中,未显示定义的子类赋值运算符会自动调用父类的赋值运算符
4.子类对象复制过程中,显示定义的子类赋值运算符不会调用父类的赋值运算符
5.子类和父类的operator=会构成同名隐藏
结论4和结论5的意思基本相同,大家可以自行验证。
3.3取地址重载
取地址主要是对象取地址还有const对象取地址,很少自己实现,在继承体系中,没有什么特殊之处,大家可以自行实现。
四、其他
4.1继承与友元
友元函数无法被继承
在父类定义的友元函数无法访问子类的私有成员和保护成员
4.2 继承与静态成员
基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一 个static成员实例 。
在运算过程中,不仅仅只考虑静态成员的特性,还需要去结合六个默认成员函数。