目录
1.继承的定义
从父类中获取一些功能接口或 数据成员,如果该成员是共有或保护成员则子类可以直接访问,提高代码的复用性。
2.继承的作用
- 提高代码的复用性
- 有利于软件版本的升级
3. 继承的语法
class 类名: 继承方式 基类名(父类名)
{
//填写派生类的成员 (子类的成员)
}
//定义一个 person基类
class person
{
private:
char name[1024];
int age;
int height;
};
//通过基类派生出一个警察类
class JC:public person
{
//新增警察的信息
private:
int power; //警察力量
int level; //级别
};
//当前这个警察就拥有所有 人的基本 信息 和自己的新增信息了
4. 类继承成员属性的访问权限
class base
{
public:
int a;
void set_base(int a,int b,int c) //没有问题,内部可以访问一切成员
{
this->a = a;
this->b = b;
this->c = c;
}
protected:
int b;
private:
int c;
};
class new_base :public base
{
public:
void set_new_base(int a,int b,int c)
{
this->a = a;
this->b = b;
// this->c = c; 错误的,私有成员只能内部访问
}
};
void set_base(int a,int b,int c)
{
base tmp;
tmp.a = a;
// tmp.b = b; 错误的,保护成员只能 子类 或 自身访问
// tmp.c = c; 错误的, 私有成员只能 自己访问。
}
总结:
1.假设想要在派生类中,直接访问基类的数据成员,那么基类的数据成员只能 设置为共有权限 或 保护权限。
2.假设想要在派生类中,访问基类的私有成员,只能在基类中设计接口,让派生类间接访问。
5. 利用参数列表,初始化父类的私有成员
6. 继承中的构造函数与析构函数
- 基类和派生类的构造函数都会执行:
构造函数的执行顺序: 先调用基类的构造函数,再调用派生类的构造函数 - 基类和派生类的析构函数都会执行:
析构函数的执行顺序: 先调派生类的析构函数,再调用基类的析构函数
总结: 在类的继承中,一定要处理好这些 基类 与派生类的构造函数 与析构函数。让派生类可以调用到 自己的构造 与 基类的构造。否则无法创建对象!
7. 总结共继承的权限问题
8.类中的隐藏问题
- 在继承中,如果子类与父类出现同名函数,则子类会把父类的功能函数给隐藏掉。假设想要在子类中使用父类被隐藏掉的接口, 是用 域操作符 指定是用父类接口 。
- 派生类中,只要编写了一个与父类同名的函数就会把父类的方法给隐藏了,不支持 重载。
- 通过父类引用 派生类 也可以调用父类的方法。 base &=new_base (通过父类引用子类)
class base { public: void show() { cout << "show base" << endl; } }; //基类 和 派生类出现了同名函数成员。 class new_base :public base { public: void show(int a,int b) //对父类的show 方法进行重载 { cout << a << endl; cout << b << endl; } }; int main() { new_base a; a.show(); //调用父类的 show 方法 ,无效的调用。因为父类的方法已经被隐藏了 a.show(10,20); //调用自己的 show 方法 //利用域操作符 ,声明是用父类的方法 a.base::show(); }
9. 类中的多继承
- 一个派生类可以继承多个基类, 获取多个基类的功能接口和数据成员,提高代码的复用性。
- 语法:
class 派生类 :继承方式 基类 ,继承方式 基类2 ........ { } 例子: class base : public base1 ,public base2 构造函数的执行顺序: base1 -> base2 -> base 析构函数的执行顺序: base -> base2 -> base1 //提示: 哪一个先继承,那么就先执行他的构造 ,从左 -》 右
- 多继承的参数列表初始化:
class base_a { public: base_a(int a):a(a){} int a; }; class base_b { public: base_b(int b):b(b){} int b; }; class base_all:public base_a ,public base_b { public: base_all(int a,int b,int c):base_a(a),base_b(b),c(c){} int c; void show() { cout << a << endl; cout << b << endl; cout << c << endl; } };
10.类中多级继承
- 语法:
class 基类名 class 派生类 :继承方式 基类名 class 派派生类 : 继承方式 派生类 例子: class base class base_a :public base class base_b :public base_a 构造函数的执行顺序: base -> base_a -> base_b 析构函数的执行顺序: base_b -> base_a -> base
- 多级继承的参数列表初始化:
11. 菱形继承(引入:虚继承)
菱形继承会出现一个二义性问题,导致派生类无法调用,基类的所有功能函数!!
菱形继承的二义性解决方式:(最强方式 : 虚继承)
1.利用 域操作符,指定使用哪一个基类中的函数方法
a.base_a::show();
a.base_b::show();
2.利用 基类引用派生类,再调用出现二义性的方法
base_a &q=a;
base_b &q=a;
3.在派生类中重写出现二义性的方法,把之前的隐藏掉。
4.最强的处理方法: 利用虚继承,让base 的空间存放在虚表中,不构造两次!!
base:
base_a :virtual public base //-> base_a 虚继承base -》 系统就会把 base 放到虚表中
base_b :virtual public base //->base_b 虚继承base -> base_b 发现虚表已经存在base了就直接使用不再分配。