C++之菱形继承

原创 2016年05月30日 13:35:53

    当我们谈C++时,我们谈些什么?

    封装,继承,多态。这是C++语言的三大特性,而每次在谈到继承时我们不可避免的要谈到一个很重要的问题——菱形继承。

a.菱形继承是什么

wKioL1dJRWXj5DLqAAERlUlgRjw139.png

    如上图,菱形继承即多个类继承了同一个公共基类,而这些派生类又同时被一个类继承。这么做会引发什么问题呢,让我们来看一段代码吧!

#include<iostream>
using namespace std;
class Base
{
protected:
	int _base;
public:
	void fun()
	{
		cout << "Base::fun" << endl;
	}
};

class A:public Base
{
protected:
	int _a;
};

class B : public Base
{
protected:
	int _b;
};
class D :public A, public B
{
private:
	int _d;
};
int main()
{
	D d;
	d.fun();//编译器报错:调用不明确
	getchar();
}

    我们可以看见D的对象模型里面保存了两份Base,当我们想要调用我们从Base里继承的fun时就会出现调用不明确问题,并且会造成数据冗余的问题,明明可以只要一份就好,而我们却保存了两份。

    那么我们可以怎样解决呢?

    第一种解决方法,使用域限定我们所需访问的函数

int main()
{
	D d;
	d.A::fun();
	d.B::fun();
	getchar();
}

    这样的做法是没有问题的,但是,这样做非常的不方便,并且当程序十分大的时候会造成我们思维混乱

    于是,C++给了我们一个别的解决方案——虚继承

b.虚继承

    虚继承是什么?

wKioL1dJS2vgVa5qAAESPEZ5yi0755.png

    如上图,虚继承即让A和B在继承Base时加上virtural关键字,这里需要记住不是D使用虚继承

    那么,虚继承又是怎么解决这些烦人的问题的呢?

wKioL1dJTcGAuLwoAAB1mzWLEJs241.png

    我们可看见在A和B中不再保存Base中的内容,保存了一份偏移地址,然后将Base的数据保存在一个公共位置处这样保证了数据冗余性的降低同时,我们也能直接的使用d.fun()来调用Base里的fun函数。

#include<iostream>
using namespace std;
class Base
{
protected:
	int _base;
public:
	void fun()
	{
		cout << "Base::fun" << endl;
	}
};

class A:virtual public Base
{
protected:
	int _a;
};

class B :virtual public Base
{
protected:
	int _b;
};
class D :public A, public B
{
private:
	int _d;
};
int main()
{
	D d;
	d.fun();
	getchar();
}

    *虚继承和虚函数是完全不同的两个概念,希望大家不要随意搞混,想要了解虚函数的同学可以看看博主的另一篇博文《C++的继承&多态》http://zimomo.blog.51cto.com/10799874/1752936


本文出自 “Zimomo” 博客,请务必保留此出处http://zimomo.blog.51cto.com/10799874/1784074

版权声明:本文为博主原创文章,未经博主允许不得转载。

C++之钻石问题和解决方案(菱形继承问题)

在C++中,什么叫做钻石问题(也可以叫菱形继承问题),怎么避免它? 下面的图表可以用来解释钻石问题。 假设我们有类B和类C,它们都继承了相同的类A。...
  • czjuttsw
  • czjuttsw
  • 2012年12月27日 14:17
  • 15967

【C++】c++单继承、多继承、菱形继承内存布局(虚函数表结构)

c++单继承、多继承、菱形继承内存布局(虚函数表结构)
  • SuLiJuan66
  • SuLiJuan66
  • 2015年10月04日 18:44
  • 2832

C++里的继承和多态(下)——单继承、多继承、菱形继承(含虚拟函数的继承)

1、带有虚函数的类 class Base { public:                  virtual void FunTest1()                 {      ...
  • lemonwxj
  • lemonwxj
  • 2016年04月20日 16:37
  • 1103

【C++基础之二十一】菱形继承和虚继承

菱形继承是多重继承中跑不掉的,Java拿掉了多重继承,辅之于接口。C++中虽然没有明确说明接口这种东西,但是只有纯虚函数的类可以看作Java中的接口。在多重继承中建议使用“接口”,来避免多重继承中可能...
  • jackyvincefu
  • jackyvincefu
  • 2014年01月05日 09:05
  • 10221

关于java 注解中元注解Inherited的使用详解

关于java中 @Inherited
  • fengge374043291
  • fengge374043291
  • 2014年09月18日 23:39
  • 6086

Delphi中inherited的详细用法

inherited就是调用祖先类的函数,如果不带参数就是默认调用同名函数 如果带参数则表明子类中的函数个数可能比祖先类要多取其中的几个参数传过去 例如 祖先类有个函数 Create(AName:...
  • alongwilliam
  • alongwilliam
  • 2014年05月20日 11:49
  • 3920

修改VS属性页中的Inherited values

原文:http://blog.csdn.net/weuro/article/details/9238423 首先在C:\Users\用户名\AppData\Local\Microsoft\M...
  • tangyin025
  • tangyin025
  • 2017年04月06日 22:52
  • 310

c++菱形继承产生的问题及解决

#include #include #include using namespace std; class A { public: A(){printf("A create.\n");} ...
  • Wonder233
  • Wonder233
  • 2016年10月18日 22:24
  • 250

C++编程输出菱形

源代码:#include using namespace std; int main() { int n, i, j; cout n; i = n - 1; j = 1; while (i >=...
  • u013732401
  • u013732401
  • 2017年03月19日 22:24
  • 1316

C++使用字符输出菱形

输入菱形对角线的对角线的字符个数n(为奇数),输入构成菱形的字符C;输出字个由字符C构成的菱形;(多组)如下; 输入: 输出: b 思路:分成两部分来输出,上部及下部,上部为字符递...
  • zzygt
  • zzygt
  • 2016年08月08日 11:34
  • 3497
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++之菱形继承
举报原因:
原因补充:

(最多只允许输入30个字)