【c++】 继承的相关问题

继承

继承:类型层次设计中提高代码的复用程度的重要手段。
派生:保持原有的属性上进行扩展,增加新属性和方法,以形成新的类型

继承权限和访问权限一样,都有三个: public protected private
派生类时可以分四步

1 .吸收基类的成员 不论是数据成员,还是函数成员,除(构造函数,拷贝构造,移动构造,赋值,移动赋值,析构函数)外全盘接收
2.改造基类成员 当父类有virtual,声明一个与基类成员同名,同参,同返回类型(返回基类指针除外)的新成员。当父类无virtual,申明一个与基类同名的函数,进行隐藏。
3.发展新成员 派生类新成员必须与基类成员不同名,它的加入保证派生类在功能上有所发展,独特的新成员才是继承与派生的核心特征
4.析构函数

无论是那种继承方式,基类继承的私有属性都无法访问

在这里插入图片描述

不论父类中的属性被啥修饰,都会被子类全盘接收

在这里插入图片描述

public,protected,private继承

在这里插入图片描述
1.通过public继承,基类里面public继承过来的,还是public,基类里面是protected,还是protected
2.通过protected继承,把基类中的public变成了protected
3.通过private继承,把基类汇总的public 和 protected 变成了private

private 继承和protected 继承都是类中可以访问,类外无法访问,这有什么区别呐?

在这里插入图片描述
通过private继承,可以把基类中的属性全部变成private,从而当子类继承时,自己类中从父类继承的属性全部无法访问

继承的内存布局

在这里插入图片描述
H类的内存布局
在这里插入图片描述

当出现多继承时,子类构建对象时,按照继承顺序,依次调用基类的构造函数

在这里插入图片描述

派生类创建对象时,每次都会默认调用基类的构造函数

在这里插入图片描述

在两个类(一个继承一个)中,如果出现相同的静态变量,虽然它俩都属于整个类,名字相同,但它们不会出现覆盖的情况,它们各种的作用域在各种的类中。

在这里插入图片描述

不想让子类继承的化话可以加final关键字

在这里插入图片描述

如果基类和子类有相同名称函数,那么在子类中,父类的该函数就会被同名隐藏起来了,

在这里插入图片描述

想调用的话,就必须加上作用域

在这里插入图片描述

就算是参数列表不同,也不能构成函数重载,必须显式的去调用

在这里插入图片描述

Y形问题:

在这里插入图片描述
调用的时候会出现二义性

显示的调用
在这里插入图片描述

菱形问题

在这里插入图片描述
调用的时候还会出现二义性

这样我们使用虚继承就可以了
在这里插入图片描述
当创建SofoBad对象时,先调用其默认的构造函数,因为它继承了其它的类,所以先调用基类构造函数,因为Sofo在Bad前面,所以先调用Sofo的构造函数,Sofo同样先调用Furuiture的构造函数,接着构造Furuiture的对象,然后构造出Sofo的对象,然后调用Bad的构造函数,同样也会先调用Furuiture的构造函数,不过因为之前已经调用过,所以不需要再次调用。

先组合,再继承

它的对象创建顺序,先按照父类对象成员属性中设计的顺序依次构造,接着构造父类对象,接着构造派生类对象。
在这里插入图片描述

先继承,再组合,同时有自己的私有属性

它的对象创建顺序,先按继承顺序构建父类对象,然后创建派生对象时,按照其成员属性的定义顺序创建对象。
在这里插入图片描述
在这里插入图片描述

继承时虚表的情况

如果一个类中有虚函数,则生成的该对象中会有一个虚指针,该指针指向一个虚表,该虚表中存储着所有虚函数的入口地址(此时这个表中没有存da函数的地址,因为它不是虚函数)
在这里插入图片描述
在这里插入图片描述

通过指针的转换调用虚函数

在这里插入图片描述

派生类继承基类的虚函数时,会将基类中的虚函数的地址原封不动的继承下来

在这里插入图片描述

当派生类重写基类中的方法后,派生类的虚表中对应的该函数将被重写,其它的函数不变

在这里插入图片描述

当派生类有虚函数时,会把自己的虚函数加入到从基类继承的虚函数的后面

在这里插入图片描述
在这里插入图片描述

当多继承时,派生类会把自己的虚函数加到第一个类的虚表指针后面

D从3个有虚函数的类继承下来,所以它里面有3个虚指针,
D类中的虚函数添加到了从A类继承下来的虚表中了
在这里插入图片描述

当基类里面有三个相同名称的虚函数,当派生类继承并改写时,会把三个虚表中的虚函数全部改了

在这里插入图片描述

公有继承:是一个

1.派生类的对象可以赋值给基类的对象(切片),这时是把派生类中从基类继承过来的隐藏对象赋值给基类对象,反过来不行,因为派生类的新成员无值可赋

2.可以将一个派生类的对象的地址赋值给基类对象,不过只能通过这个指针访问派生类中由基类继承过来的隐藏对象,不能访问派生类中的新成员。

3.派生类对象可以可以初始话基类的引用,但这个别名只能包含派生类对象中由基类继承过来的隐藏对象

同时,赋值重载也也一样,不过我们可以通过指针强制来解决


class Base
{
private:
	int b_value;
public:
	Base(int value = 0) :b_value(value) { std::cout << "Create Base" << std::endl; }
	Base(const Base& base) :b_value(base.b_value) { std::cout << "Copy Base" << std::endl; }
	Base& operator =(const Base& base)
	{
		if (this != &base)
		{
			b_value = base.b_value;
		}
		

	}

};
class Child :public Base
{private:
	int c_value;
public:
	Child(int value = 0) :c_value(value) { std::cout << "Create Chile" << std::endl; }
	Child(const Child& child) :c_value(child.c_value) 
	{
		Base(child); 
		std::cout << "Copy Child" << std::endl;
	}
	Child& operator =(const Child& child)
	{
		if (this != &child)
		{
			*(Base*)this = child;
			c_value = child.c_value;
		}
	  

	}

};

隐藏

非虚函数:只要子类与父类中的函数名相同
虚函数:子类中的函数与父类中函数的名字相同,参数不同,当子类中的函数与父类中函数名字,参数,返回值相同时则为重写。

注意

1.当派生类继承基类中的纯虚函数时,派生类只继承了基类中的函数名字,函数具体的实现是由派生类来实现的
2.假如给虚函数返回值写 return 0.0f;它实现了一部分,因此也不会强制派生类实现这个函数
3.不要同名隐藏基类中的非虚方法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值