栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

C++继承(复习用)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++继承(复习用)

文章目录
  • 三种继承关系与三种访问限定符的关系
  • 父类和子类对象赋值转换(切片)
  • 隐藏的定义及和重载的区别
  • 子类的默认构造函数怎么写
    • 子类构造函数
    • 子类拷贝构造函数
    • 子类赋值运算符重载
    • 子类析构
  • 杂项(了解即可)
  • 菱形继承
    • 数据冗余和二义性
    • 虚继承作用及操作
    • 虚继承原理
  • 组合和继承

三种继承关系与三种访问限定符的关系

总结一下:说了3个东西,知道的可以跳过

  1. 只用public继承
  2. 父类不要用private成员,因为子类无法直接访问
  3. 继承与访问限定符的关系是权限缩小
类成员/继承方式public继承protected继承private继承
基类的public成员派生类的public成员派生类的protected成员派生类的private成员
基类的protected成员派生类的protected成员派生类的protected成员派生类的private成员
基类的private成员在派生类中不可见在派生类中不可见在派生类中不可见

通过这张表可以得出一个规律,继承关系与访问限定符的关系是min的关系。

ps:其实计算机很多设计都是设计成权限缩小的。在读写问题上也是如此。因此这个规律也很好记。

举个例子:public成员被protected继承,min(public, protected) = protected,因此派生类继承下来的父类成员在子类是protected的。

还有一个重点:我们看到父类的private成员不管是什么继承,在子类都是看不见的。看不见只是不可以使用的意思,并不是没有继承下来。

如图:

ps:子类是不能直接访问父类的私有成员,但不是不能访问,父类可以拿一个函数接口来获取父类的私有成员。

这是语法规定,好处是可以保证封装性。同时我们发现,protected成员在public和protected继承下,分别在子类是public和protected的,可以被子类访问。

如图:

注:protected和private在非继承情况下都是类外不可访问,没有区别。protected和private只有在继承的情景下才有区别。在继承情景下:父类的private成员子类是不可以直接访问的,父类的protected成员子类在public和protected继承方式下是可以直接访问的。

可以认为protected就是为了继承情景才产生的。

所以一般父类成员一般都是public或者protected,很少用private。


父类和子类对象赋值转换(切片)

总结一下:这里知道四个东西即可,知道的可以跳过
1.对象切片
2.指针切片
3.引用切片
4.子类切片给父类(父类不能给子类)


所谓切片,肯定是大的切给小的,因此是子类切片给父类。(父类不能给子类)

切片有三种形式,对象切片,指针切片,引用切片。

隐藏的定义及和重载的区别

总结一下:若知道的可以跳过

  1. 隐藏指父子类成员重名时,子类只能看见自己的成员
  2. 隐藏是不同作用域成员名相同,重载是相同作用域函数名相同
  3. 父子类成员不要同名,也就是不要出现隐藏。

隐藏是指父类和子类成员名(函数或者变量)相同,子类继承下来后子类只会看到子类自己的成员。


若想调用父类的func,要加作用域限定符::

这里和函数重载做一下区别:

虽然它们参数不同,但是两个func并不构成重载。因为重载的前提是在同一个作用域。由于这是两个不同的作用域,因此是隐藏。

子类的默认构造函数怎么写

总结:这里不要跳过,全部看完

  1. 子类构造函数组成部分:显示调用父类构造+子类成员初始化
  2. 子类拷贝构造组成部分:显示调用父类拷贝构造+子类拷贝自己的成员
  3. 子类赋值运算符重载组成部分:显示调用父类运算符(加作用域限定符)+子类拷贝自己成员
  4. 子类析构函数组成部分:只析构子类的成员,父类析构不准调用,因为C++自己会帮你调用
  5. 对于子类对象,先构造父类部分,再构造子类部分,先析构子类部分,再析构父类部分。(创建对象就是压栈,析构对象就是出栈)
  6. 背住后自己写一遍这四个默认构造函数就会了。
子类构造函数

父类

	person(string _s)
	{
		name = _s;
	}

子类

stu(string s, int _id)
		:person(s)
		,id(_id)
	{}

ps:person是自定义类型,如果person没有默认构造函数,必须用初始化列表初始化。

子类拷贝构造函数

父类

	person(const person& p)
	{
		name = p.name;
	}

子类

	stu(const stu& s)
		:person(s)
		,id(s.id)
	{}

ps:拷贝构造中,person是自定义类型,必须要用初始化列表初始化。因为person的拷贝构造不可能是默认构造函数。

子类赋值运算符重载

父类

	person& operator=(const person& p)
	{
		if (this != &p)
		{
			name = p.name;
		}
	}

子类

	stu& operator=(const stu& s)
	{
		person::operator=(s);
		id = s.id;
	}

注意:这里子类调用父类的赋值运算符重载函数必须要指定作用域,否则子类会隐藏父类的operator=,导致自己调用自己,陷入死递归。

子类析构

父类

	~person(){}

子类

	~stu(){}

不允许写person::~person(),这样会对父类的内存空间析构两次。

杂项(了解即可)
  1. 友元关系不能被继承
  2. 父类的静态成员子类继承后两个静态成员是同一个
  3. 如果要写一个不能被继承的类,让父类的构造函数是private就可以了。因为子类无法调用父类的构造函数,因此子类也无法创建对象
  4. 可以用静态成员来计算子类一共创建了多少次,只要在父类的构造函数中对这个静态成员++。每次创建一个子类对象,子类对象去调用父类对象的构造函数,会让静态成员++。(虽然这种写法没什么卵用)
菱形继承

总结关键点:知道的跳过即可,不知道的重点复习+自己写一个菱形继承来验证。

  1. 菱形继承的缺点:数据冗余+二义性
  2. 虚继承的作用和如何写虚继承
  3. 虚继承原理

数据冗余和二义性

此处简易自己写一个菱形继承来验证一下。

  1. 数据冗余很好理解,就是student有一个name,teacher也有一个name。
  2. 二义性就是当我访问name这个成员的时候,编译器不知道我访问的是student的name还是teacher的name。

二义性可以用作用域限定符来解决。但是数据冗余暂时没有办法解决。

虚继承作用及操作

关键字:virtual。虚继承可以解决二义性和数据冗余问题。

在哪里写virtual呢?在菱形的腰部加上virtual

虚继承原理

总结一下:看得懂这句话和这个图就可以跳过了。看不懂建议自己写代码看底层结构。
虚继承的类会存多一个指针的地址,这个指针指向一个内存,这个内存被称为虚基表。虚基表里面存的是虚继承的类离父类成员变量的地址偏移量(单位是字节)

关系:

底层:

验证一下上面的底层结构是否如此:
关系结构代码如下:就是上面那个图的关系。

class a
{
public:
	int a;
};

class b : virtual public a
{
public:
	int b;
};

class c :virtual  public a
{
public:
	int c;
};

class d : public b, public c
{
public:
	int d;
};


int main()
{
	D d;
	d.a = 1;
	d.b = 2;
	d.c = 3;
	d.d = 4;
}

打开内存,看&d的内存分布。如下:

我们说了,红色圈起来的是指向虚基表的指针,现在去看一下这两个指针。
可以发现,14和0c就是对应的偏移量,在10进制下,分别是20和12.

自己去算一下,刚好就是B到A成员的偏移量和C到A成员的偏移量大小



ps:第一行是空着的,和多态+菱形继承+虚继承有关。这一行是为了存自己的类的虚表指针的偏移量。一般都是向上挨着的,因此一般是-4,也就是往上4个字节。
如果想了解,建议写代码去调试看。
如果不想了解,背住这个是存离自己的虚表指针的偏移量,一般为4即可。

写代码验证的时候,A类写一个虚函数,B类写一个虚函数,C类写一个虚函数,D类写一个虚函数。然后调试你就可以看到这个完整的过程了。(重不重写虚函数对现象没有影响,毕竟重写只是覆盖虚表里面的函数指针而已)


组合和继承

知道以下几点即可:

  1. 关系是is-a就用继承,关系是has-a就用组合
  2. 关系不明确的就用组合就用组合
  3. 组合无法访问其他对象的保护成员,有封装性和高内聚。继承可以访问父类的保护成员,耦合性提高了。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/835916.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号