【继承】复杂的菱形继承

这篇具有很好参考价值的文章主要介绍了【继承】复杂的菱形继承。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【继承】复杂的菱形继承,C++进阶,c++,开发语言,visualstudio

博主首页: 有趣的中国人
 

专栏首页: C++进阶
 


本篇文章主要讲解 菱形继承 的相关内容

目录

1. 继承与友元

2. 继承与静态成员

3. 复杂的菱形继承及菱形虚拟继承

3.1 继承分类

3.2 菱形继承导致的问题

3.3 虚拟继承解决数据冗余的原理

4. 继承和组合的区别


 1. 继承与友元

友元关系不能继承,也就是说,基类的友元函数不能访问子类的保护和私有成员。

class Student;
class Person
{
public:
	friend void Display(const Person& p, const Student& s);
protected:
	string _name = "Jason"; // 姓名
};
class Student : public Person
{
protected:
	int _stuNum; // 学号
};
void Display(const Person& p, const Student& s)
{
	cout << p._name << endl;
    // 此处不能访问
	//cout << s._stuNum << endl;
}
void main()
{
	Person p;
	Student s;
	Display(p, s);
}

2. 继承与静态成员

基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子
类,都只有一个static成员实例
 

我们可以利用这个特性计算构造出了多少个继承的对象,只要在构造函数中每次将静态成员变量自增1即可。

class Person
{
public:
	Person() { ++_count; }
protected:
	string _name; // 姓名
public:
	static int _count; // 统计人的个数。
};

int Person::_count = 0;

class Student : public Person
{
protected:
	int _stuNum; // 学号
};

class Graduate : public Student
{
protected:
	string _seminarCourse; // 研究科目
};

void TestPerson()
{
	Student s1;
	Student s2;
	Student s3;
	Graduate s4;
	cout << " 人数 :" << Person::_count << endl;
	Student::_count = 0;
	cout << " 人数 :" << Person::_count << endl;
}

int main()
{
	TestPerson();
	return 0;
}

3. 复杂的菱形继承及菱形虚拟继承

3.1 继承分类

单继承

一个子类只有一个直接父类叫做做单继承。

【继承】复杂的菱形继承,C++进阶,c++,开发语言,visualstudio

多继承

一个子类有两个即以上的直接父类叫做多继承。

【继承】复杂的菱形继承,C++进阶,c++,开发语言,visualstudio

菱形继承

菱形继承是特殊的多继承。

【继承】复杂的菱形继承,C++进阶,c++,开发语言,visualstudio

3.2 菱形继承导致的问题

菱形继承可能导致两个问题:

1. 在上面的菱形继承中,假设Person中有一个成员变量_name,那么在Student和Teacher中也会有一个成员变量_name,然而Assistant继承了Student和Teacher,在Assistant中就会有两份_name,会导致数据冗余。 

【继承】复杂的菱形继承,C++进阶,c++,开发语言,visualstudio

2. 在访问Assistant中的_name时,由于不知道要访问的到底是哪个_name,是Student还是Teacher呢?就会有二义性的问题。 

class Person
{
public:
	string _name;
};

class Student : public Person
{
protected:
	int _stuid;
};

class Teacher : public Person
{
protected:
	int _teacherid;
};

class Assistant : public Student, public Teacher
{
protected:
	string _majorCourse;
};

void test()
{
	Assistant ast;
	// 这里会有二义性的问题,不知道访问的是哪一个类中的
	ast._name = "a";

	// 指定作用域可以解决二义性的问题,但是无法解决数据冗余的问题
	ast.Teacher::_name = "xxx";
	ast.Student::_name = "yyy";
}

可以用虚拟继承来解决数据冗余的问题,只需要在Student和Teacher的继承Person时使用虚拟继承,加virtual关键字。

class Student : virtual public Person
{
protected:
	int _stuid;
};

class Teacher : virtual public Person
{
protected:
	int _teacherid;
};

 3.3 虚拟继承解决数据冗余的原理

我们可以用内存窗口调试下面这段代码:

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

int main()
{
	D d;
	d.B::_a = 1;
	d.C::_a = 2;
	d._b = 3;
	d._c = 4;
	d._d = 5;
	return 0;
}

如果不加virtual:

很明显_a有两份

【继承】复杂的菱形继承,C++进阶,c++,开发语言,visualstudio

 如果加了virtual:

【继承】复杂的菱形继承,C++进阶,c++,开发语言,visualstudio

 那么在B类和C类中,除了存储了继承下来的成员变量,头部存储的是个地址,我们可以看一下:

【继承】复杂的菱形继承,C++进阶,c++,开发语言,visualstudio

【继承】复杂的菱形继承,C++进阶,c++,开发语言,visualstudio

这个地址存储的含义是这个位置距离共同继承的A的偏移量,虚拟继承之后共同继承的部分就只有一份了,就解决的数据冗余的问题,我们可以用计算器验证以下:

【继承】复杂的菱形继承,C++进阶,c++,开发语言,visualstudio

【继承】复杂的菱形继承,C++进阶,c++,开发语言,visualstudio 所以我们可以看出虚拟继承在内存中的存储方式:

【继承】复杂的菱形继承,C++进阶,c++,开发语言,visualstudio


4. 继承和组合的区别

1. public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象。
2. 合是一种has-a的关系。假设B组合了A,每个B对象中都有一个A对象。
3. 优先使用对象组合,而不是类继承
4. 继承允许你根据基类的实现来定义派生类的实现。这种通过生成派生类的复用通常被称
为白箱复用(white-box reuse)。术语“白箱”是相对可视性而言:在继承方式中,基类的
内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很
大的影响。派生类和基类间的依赖关系很强,耦合度高。
5. 对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象
来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复
用(black-box reuse),因为对象的内部细节是不可见的。对象只以“黑箱”的形式出现。
组合类之间没有很强的依赖关系,耦合度低。优先使用对象组合有助于你保持每个类被
封装。
6. 实际尽量多去用组合。组合的耦合度低,代码维护性好。不过继承也有用武之地的,有
些关系就适合继承那就用继承,另外要实现多态,也必须要继承。类之间的关系可以用
继承,可以用组合,就用组合。文章来源地址https://www.toymoban.com/news/detail-855496.html

到了这里,关于【继承】复杂的菱形继承的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • C++--菱形继承

    C++--菱形继承

    1.什么是菱形继承         单继承:一个子类只有一个直接父类时称这个继承关系为单继承                                            多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承 菱形继承的问题:菱形继承有数据冗余和二义性

    2024年02月15日
    浏览(5)
  • C++:面向对象大坑:菱形继承

    C++:面向对象大坑:菱形继承

    单继承:一个子类只有 一个直接父类 时称这个继承关系为单继承。 图示: 多继承:一个子类有 两个或以上直接父类 时称这个继承关系为多继承。 图示: 1.概念 菱形继承:菱形继承是多继承的一种特殊情况。即:一个类是另外几个类的子类,而这几个子类又是另外一个类

    2024年04月27日
    浏览(11)
  • 【C++练级之路】【Lv.12】继承(你真的了解菱形虚拟继承吗?)

    【C++练级之路】【Lv.12】继承(你真的了解菱形虚拟继承吗?)

    快乐的流畅:个人主页 个人专栏:《C语言》《数据结构世界》《进击的C++》 远方有一堆篝火,在为久候之人燃烧! 继承(inheritance),是面向对象的三大特性之一。 它是面向对象编程中, 使代码可以复用 的最重要的手段,它允许程序员在 保持原有类特性的基础上进行扩展

    2024年03月14日
    浏览(9)
  • 【VisualStudio】使用 C++ 语言开发 Qt 环境配置教程

    【VisualStudio】使用 C++ 语言开发 Qt 环境配置教程

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 先上一张效果图,具体步骤主要分为以下三步。 这一步不再赘述,注意一定要安装 C++ 语言。 可以参考这个教程 Visual Studio 2022安装与使用教程。 这一步也不再赘述,网上搜索教

    2024年02月10日
    浏览(12)
  • C++中菱形继承中的多态在底层是如何实现的。

    C++中菱形继承中的多态在底层是如何实现的。

    如果还不了解菱形继承和多态的底层可以看这两篇文章: C++中多态的底层实现_Qianxueban的博客-CSDN博客 C++的继承以及virtual的底层实现_Qianxueban的博客-CSDN博客

    2024年02月09日
    浏览(11)
  • 【VisualStudio】基于 Visual Studio 使用 C++ 语言开发 Qt 环境配置教程

    【VisualStudio】基于 Visual Studio 使用 C++ 语言开发 Qt 环境配置教程

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 先上一张效果图,具体步骤主要分为以下三步。 这一步不再赘述,注意一定要安装 C++ 语言。 可以参考这个教程 Visual Studio 2022安装与使用教程。 这一步也不再赘述,网上搜索教

    2024年02月15日
    浏览(13)
  • 想要入坑C++?当我拿出菱形虚拟继承,阁下又该如何应对

    想要入坑C++?当我拿出菱形虚拟继承,阁下又该如何应对

    🌸作者简介: 花想云 ,目前大二在读 ,C/C++领域新星创作者、运维领域新星创作者、CSDN2023新星计划导师、CSDN内容合伙人、阿里云专家博主、华为云云享专家致力于 C/C++、Linux 学习 🌸 本文收录于 C++系列 ,本专栏主要内容为 C++ 初阶、C++ 进阶、STL 详解等,专为大学生打造

    2024年02月07日
    浏览(11)
  • 【浅尝C++】继承机制=>虚基表/菱形虚继承/继承的概念、定义/基类与派生类对象赋值转换/派生类的默认成员函数等详解

    【浅尝C++】继承机制=>虚基表/菱形虚继承/继承的概念、定义/基类与派生类对象赋值转换/派生类的默认成员函数等详解

    🏠专栏介绍:浅尝C++专栏是用于记录C++语法基础、STL及内存剖析等。 🎯每日格言:每日努力一点点,技术变化看得见。 我们生活中也有继承的例子,例如:小明继承了孙老师傅做拉面的手艺。继承就是一种延续、复用的方式。C++为了提高代码的可复用性,引入了继承机制,

    2024年04月10日
    浏览(14)
  • C语言打印各种三角形和菱形(包括星形菱形与空白格菱形)

    C语言打印各种三角形和菱形(包括星形菱形与空白格菱形)

    多重循环,也称嵌套循环,由一个外层循环和一个或多个内层循环组成。 for循环在C语言基础中占有重要地位,其中最能体现for的多重循环的就是打印各种形状的三角形,进而根据打印各种三角形的规律合并打印出菱形。 首先,我们来打印最简单的几个不同的三角形: 靠右直

    2024年02月04日
    浏览(10)
  • C语言打印菱形

    C语言打印菱形

    题目:输入对角线长度,打印对应的菱形(对角线必须是奇数,否则打印出的不是菱形) 代码如下:

    2024年01月24日
    浏览(8)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包