【第22期】观点:IT 行业加班,到底有没有价值?

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++ 对象的内存布局(上) 陈皓http://blog.csdn.net/haoel  点击这里查看下篇>>>前言 07年12月,我写了一篇《C++虚函数表解析》的文章,引起了大家的兴趣。有很多朋友...
  • haoel
  • haoel
  • 2008-10-15 20:36
  • 124007

C++ 对象的内存布局(下)

C++ 对象的内存布局(下) 陈皓http://blog.csdn.net/haoel  <<<点击这里查看上篇  重复继承 下面我们再来看看,发生重复继承的情况。所谓重复继承,也就是某个基类被间接地...
  • haoel
  • haoel
  • 2008-10-15 20:59
  • 53097

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

Fork 系统炸弹

这个炸弹很简单,就是一个命令行,如下所示::(){ :|:& };:在此,我严重警告你,请不要在你的Unix/Linux或Cygwin的Shell下执行这个命令。否则,这个命令会不停地fork子进程,...
  • haoel
  • haoel
  • 2009-02-11 09:43
  • 6945

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

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

C/C++返回内部静态成员的陷阱

C/C++返回内部静态成员的陷阱陈皓背景在我们用C/C++开发的过程中,总是有一个问题会给我们带来苦恼。这个问题就是函数内和函数外代码需要通过一块内存来交互(比如,函数返回字符串),这个问题困扰和很多...
  • haoel
  • haoel
  • 2006-11-16 17:10
  • 24815

深入浅出单实例Singleton设计模式

深入浅出单实例Singleton设计模式陈皓前序单实例Singleton设计模式可能是被讨论和使用的最广泛的一个设计模式了,这可能也是面试中问得最多的一个设计模式了。这个设计模式主要目的是想在整个系统...
  • haoel
  • haoel
  • 2009-03-26 23:46
  • 46238

标准C++类string的Copy-On-Write技术(一)

标准C++类std::string的内存共享和Copy-On-Write技术 陈皓1、             概念 Scott Meyers在《More Effective C++》中举了个例子,不...
  • haoel
  • haoel
  • 2004-06-23 16:06
  • 53176

菱形继承引发的问题和解决方案,以及底层实现的原理.

定义:两个子类继承同一个父类,而又有子类同时继承这两个子类。          如果直接继承会引发访问不明确(二义性),以及数据冗余。如果直接指定访问对象,可解决二义性(第一段代码以及解析图),而要解...

CPP学习一菱形继承特点

CPP的菱形继承的情况,如果不使用虚继承,这将会导致内存中有两份顶端基类的对象。这是内存上的浪费,而且大多数情况我们希望的并不是这样。所以要使用虚继承,这样能使得顶端的基类只有一份。使用方法就是在第二...

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

在C++中,什么叫做钻石问题(也可以叫菱形继承问题),怎么避免它? 下面的图表可以用来解释钻石问题。 假设我们有类B和类C,它们都继承了相同的类A。...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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