c++复盘笔记7(继承)

文章目录

  • 继承
    • 三种继承方式
    • 派生类的构造和析构
    • 类型兼容
    • 多继承的二义性问题
      • 虚基类

继承

单继承:一个派生类继承一个基类
多继承:一个派生类继承多个基类
class B
calss A:public/protected/private B
{

};//A继承B

三种继承方式

注意:默认的继承方式是private

public:

基类的publicprotected成员的访问属性在派生类中保持不变,但基类的private成员不可直接访问。
派生类中的成员函数可以直接访问基类中的publicprotected成员,但不能直接访问基类的private成员。
通过派生类的对象访问从基类继承的成员,只能访问public成员。

protectetd:

基类的publicprotected成员都以protected身份出现在派生类中,但基类的private成员`不可直接``访问。
派生类中的成员函数可以直接访问基类中的publicprotected成员,但不能直接访问基类的private成员。
通过派生类的对象不能直接访问从基类继承的任何成员。

private:

基类的publicprotected成员都以private身份出现在派生类中,但基类的private成员不可直接访问。
派生类中的成员函数可以直接访问基类中的publicprotected成员,但不能直接访问基类的private成员。
通过派生类的对象不能直接访问从基类继承的任何成员。

派生类的构造和析构

构造:
当使用派生类创建对象的时候 首先会创建一个基类的对象 依附于派生类的对象中 如果派生类的新增成员中还有其他类的对象 派生类的数据成员 其实还间接地包含了这些对象的数据成员
所以在构造派生类的对象的时候要对基类数据成员 新增数据成员 内嵌对象的数据成员进行初始化

派生类的构造函数的一般格式:

派生类名(参数总表):基类名1(基类参数表1,基类名2(基类参数表2),....,基类名n(基类参数表n),子对象名1(子对象参数表1),子对象名2(子对象参数表2),.....,子对象名m(子对象参数表m)
{
}

注意:
1、初始化列表中基类名和子对象名的顺序无关紧要
2、当基类或者子对象没有有参构造的时候可以不用写基类的初始化列表 系统会默认地调用基类地无参构造函数 只有当基类后者子对象有有参构造函数的时候才要在初始化列表中初始化它们,这样它们在调用自己的构造函数的时候就会在给出的参数表中找参数

创建派生类对象时构造函数调用顺序:
调用基类的构造函数–>按照成员对象定义的顺序调用成员对象的构造函数–>调用派生类的构造函数

析构:
派生类的析构函数只负责清理派生类中的非对象数据成员 至于基类和成员对象会自动调用它们各自的析构函数

派生类对象析构时析构函数的调用顺序:
和构造函数调用顺序相反
派生类的析构函数–>和定义顺序相反的成员对象的析构函数–>基类的析构函数

类型兼容

1、派生类对象可以作基类对象使用(也可以理解为公有继承的原因)。
2、派生类对象可以初始化基类对象。
3、派生类对象可以赋值给基类对象。
4、派生类对象可以初始化基类的引用。
5、派生类对象的地址可以赋给指向基类的指针。
如果函数的参数是某类的对象,那么传给该参数的可以是该类的对象,而且可以是该类的任何派生类对象,而且不必去重载这个函数。

多继承的二义性问题

由于派生类可以继承多个基类,多个基类中拥有同名成员,当派生类对象调用同名成员的时候怎么区分调用的是哪个基类的成员呢,这里就出现了二义性问题。
解决办法:1、加上类作用域说明符
2、使用虚基类
3、同名覆盖,也就是在派生类中重写一遍
上代码看:

#include<iostream>
using namespace std;
class A {
	void show()
	{
		cout << "A::show()" << endl;
	}
};
class B {
	void show()
	{
		cout << "B::show()" << endl;
	}
};
class C :public A, public B
{


};
int main()
{
	C c;
	c.show();
}

在这里插入图片描述
1、加上啊类说明符
在这里插入图片描述

虚基类

当在多条继承路径上有一个公共的基类,在这些路径中的某几条汇合处,这个公共的基类就会产生多个实例(或多个副本),若只想保存这个基类的一个实例,可以将这个公共基类说明为虚基类。
在继承中产生歧义的原因有可能是继承类继承了基类多次,如概述图所示,子类C最后会接受分别来自A和B的同一个或多个相同拷贝,从而产生了多个拷贝,即不止一次的通过多个路径继承类在内存中创建了基类成员的多份拷贝。而这些是A和B从父类继承而来,所以C类该继承A还是B传下来的还是都接受呢?这样就产生歧义,虚基类的基本原则是在内存中只有基类成员的一份拷贝。这样,通过把基类继承声明为虚拟的,就只能继承基类的一份拷贝,从而消除歧义。用virtual限定符把基类继承说明为虚拟的。

在这里插入图片描述

上图所示的继承关系也叫***菱形继承或者钻石继承***

注意:当子类AB同时虚继承父类的时候,如果父类中的虚函数在子类A B中都重写了那么在子类c中必须也要重写 因为子类c不可能同时继承B,C重写的父类中的函数 如果AB都没重写或者只重写了其中一个那么子类C中可以不重写

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pp不会算法^v^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值