继承
在C++中,我们常要对某个函数进行多次复用,例如: 信息管理系统中,对于教师、学生、教务人员等"类"而言,有部分信息是通用的:姓名,性别,年龄,联系方式等。如果为每一种角色都编写一个"类",会有不少重复的代码,造成效率上的浪费。
C++ 的“继承”机制就能避免上述浪费,减少代码复用
- 在 C++ 中,从一个类派生出另一个类的写法如下
class 派生类名: 继承方式说明符 基类名{
...
};
继承方式可以声明为: protect (保护继承),public(公有继承),private(私有继承)
- 派生类对象占用的存储空间大小,等于基类对象占用的存储空间大小加上派生类对象自身成员变量占用的存储空间大小。
class Base
{
int a;
int b;
};
class Derived :public Base
{
int c;
};
int main()
{
cout<<"Base:"<<sizeof(Base)<<endl; // 8
cout<<"Derived"<<sizeof(Derived)<<endl; //12
system("pause");
return 0;
}
Protected 保护继承
引入:基类的成员本来就是派生类的成员,因此对于那些出于隐藏的目的不宜设为公有,但又确实需要在派生类的成员函数中经常访问的基类成员,将它们设置为保护成员,既能起到隐藏的目的,又避免了派生类成员函数要访问它们时只能间接访问所带来的麻烦。
权限:能访问成员的地方就能访问公有成员
保护成员扩大的访问范围表现在:基类的保护成员可以在派生类的成员函数中被访问。
class Student
{
public:
char name[20];
int age;
protected:
int id;
private:
int sex;
};
class Mstudent :public Student
{
void show()
{
name[20]='jack'; //可以访问
age = 10; //可以访问
id = 001;//可以访问
sex = 0; //error: 不能访问基类的私有成员
Student A;
A.id //error ,A不是函数所作用的对象,不能访问其保护成员
Mstudent B;
B.id = 002;
B.sex = 0; //error :不能访问基类的私有成员
}
};
int main()
{
Mstudent C;
int n;
n=C.age; // ok
int m ;
m=C.id ; //error 不在派生类成员函数内,不能访问基类保护成员
system("pause");
return 0;
}
注意以下三点:
- 在类的成员函数外部,不能访问对象的私有成员和保护成员。
- 派生类的成员函数中不能访问基类的私有成员。
- 派生类的成员函数中可以访问基类的保护成员。
三种继承方式的访问权限如下表
继承方式 | 基类的访问权限 | 派生类的访问权限 | 外部的访问权限 |
public | public | public | Yes |
protected | protected | No | |
private | 不可访问 | No | |
protected | public | public | No |
protected | protected | No | |
private | 不可访问 | No | |
private | public | private | No |
protected | private | No | |
private | 不可访问 | No |
基类的公有成员经过私有派生后,在派生类中变为私有成员。(以此类推)
不可访问: 指的是类的成员函数内部也不能访问的成员。
Base中的private成员,在Derived中的成员函数中不能访问,但是它依然是派生类的成员。
C++派生类和赋值运算符
如果基类重载了赋值运算符
=
而派生类没有,那么在派生类对象之间赋值,或用派生类对象对基类对象进行赋值时,其中基类部分的赋值操作是调用被基类重载的=
完成的。
同名成员的访问方式:
- 重载
在基类或者派生类同一个类作用域当中的
函数名相同,参数列表不同
- 隐藏
方法分布在基类和派生类中
方法名字相同,就说派生类的同名方法把基类的同名方法给隐藏了
- 覆盖
方法分布在基类和派生类中
基类的方法是虚函数,派生类的方法和基类的虚函数,返回值相同,函数名相同,
参数列表也相同,那么此时派生类的这个函数自动处理成虚函数,和基类的函数成为
覆盖关系, 在虚函数表中进行覆盖!<虚函数表以及虚函数在《C++ 继承和多态(二)中有详细讲解》>
问题:
【1】如果不写继承方式,如何访问?
- 取决于类的定义为struct / class struct 默认为公有继承 class 默认为私有继承
【2】派生类对象如何构造?
- 在派生类构造函数的初始化列表中,指定基类成员的构造方式