c++继承(二)

一、友元函数的继承

友元函数不能被继承,就像爸爸的朋友不是你的朋友,如果要有友元函数,在子类重新定义一个。

二、静态成员的继承

静态成员的继承仍然是那个成员,普通成员的继承是不同的。

父类的静态成员属于当前类,也属于当前类的派生类。

三、单继承与多继承

1、单继承

一个子类只有一个直接父类

2、多继承

一个子类有两个或以上的直接父类

四、菱形继承

1、理解

如图 Assistant 就是一个菱形继承,显然如果不做特殊处理 Assistant 里面会有两份 Person 类中的成员,这就导致了数据冗余和二义性。

解决办法就是在菱形继承中父类被继承两次的地方进行虚继承virtual

被继承的 Person 类是虚基类。

2、剖析

(1)未用 virtual

cpp 复制代码
class A
{
public:
	int _a;
};

class B : public A
//class B : virtual public A
{
public:
	int _b;
	int _b1;
	int _b2;

};

class C : public A
//class C : virtual public A
{
public:
	int _c;
};
class D : public C, public B
{
public:
	int _d;
};

int main()
{
	D d;
	d.B::_a = 1;
	d.C::_a = 2;

	//d._a = 0;
	d._b = 3;
	d._c = 4;
	d._d = 5;
}

上图就是典型的菱形继承且没有解决,这样在D类中我们发现两个_a是不一样的,要想使用必须指定类域,这就是数据冗余和二义性。

内存级理解:

明显的看到内存中D对象中的B,C存有不同的_a,这是不被允许的。

(2)用 virtual

cpp 复制代码
class A
{
public:
	int _a;
};

//class B : public A
class B : virtual public A
{
public:
	int _b;
	int _b1;
	int _b2;

};

//class C : public A
class C : virtual public A
{
public:
	int _c;
};
class D : public C, public B
{
public:
	int _d;
};

int main()
{
	D d;
	d.B::_a = 1;
	d.C::_a = 2;

	d._a = 0;
	d._b = 3;
	d._c = 4;
	d._d = 5;
}

上图我们用虚继承解决了问题,此时类D中的_a是同一个_a,所以最后_a值应该是0

内存级理解:

首先B,C类中不再存有_a的值,而是用一个地址代替了,_a的值被放到了D对象的内存最下面,地址所指向的内容存放的是_a的值0,还有十六进制的偏移量,用来找到原内存中_a的存储位置。

这样就解决了问题。

(3)总结

a、存地址的偏移量是为了方便找到数据,方便切片。

b、虚继承的解决原理:把原来存父类成员的地方存地址,通过地址和偏移量找到唯一的父类成员。实现原来有几个类继承就有几份父类成员的数据冗余变成现在存几个地址和偏移量来找到内存中唯一的一份父类成员,解决了数据冗余和二义性。

c、对象的存储按声明顺序存储。

五、继承和组合

我们发现继承和组合都能复用之前的类,两者是相似的,在实践中两者也会一起使用。

cpp 复制代码
//父类
class A {};

//继承
class B : public A
{
    //直接继承,直接使用
};

//组合
class C
{
private:
    A _aa;  //创建 A 对象,使用成员及方法
}

|----|-------------------------------------------------------------------------|
| 方式 | 备注 |
| 继承 | is_a关系,白箱复用(在继承方式中,基类的 内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很大的影响)耦合度高。 |
| 组合 | has_a关系,黑箱复用(为对象的内部细节是不可见的)耦合度低。 |

优先使用组合,组合的耦合度低,代码维护性好。

相关推荐
VBA633710 分钟前
VBA之Word应用第四章第二节:段落集合Paragraphs对象(二)
开发语言
点云SLAM38 分钟前
C++ 常见面试题汇总
java·开发语言·c++·算法·面试·内存管理
xiaowu0801 小时前
策略模式-不同的鸭子的案例
开发语言·c#·策略模式
edjxj2 小时前
Qt图片资源导入
开发语言·qt
qq_25929724732 小时前
QT-事件
开发语言·qt
专注VB编程开发20年2 小时前
CSS 的命名方式像是 PowerShell 的动词-名词结构,缺乏面向对象的层级关系
开发语言·后端·rust
古译汉书2 小时前
嵌入式铁头山羊stm32-ADC实现定时器触发的注入序列的单通道转换-Day26
开发语言·数据结构·stm32·单片机·嵌入式硬件·算法
UnnamedOrange3 小时前
ROS2 配置 linter 的代码格式化工具为 clang-format
c++·cmake
Dobby_053 小时前
【面试题】C++系列(一)
c++·面经
计算机毕业设计木哥3 小时前
计算机毕设选题:基于Python+Django的B站数据分析系统的设计与实现【源码+文档+调试】
java·开发语言·后端·python·spark·django·课程设计