2020-10-28

C++虚继承可以防止多重继承产生的二义性问题。

        虚继承,就是在被继承的类前面加上virtual关键字,这时被继承的类称为虚基类,如下面代码中的base类。虚继承在多重继承的时可以防止二义性。

    class base

    class derived1 : virutal public base

    class derived2 : virtual public base

    class derived3 : public derived1, public derived2

以上的代码如果用到了base中的某个成员变量就不会产生二义性。和#progma once在头文件中的作用类似。请看下面的例子:

#include <iostream>

using namespace std;

class Parent

{

public:

      int p;                                           // p将会被所有的子类继承,也将是二义性的根源

      inline Parent()

      {

               p = 10;

      }

};

class Child1 : public Parent

{

public:

      int c1;

      inline Child1()

      {

               p = 12;                           // p在子类Child1中被赋值为12

               c1 = 12;

      }

};

class Child2 : public Parent

{

public:

      int c2;

      inline Child2()

      {

               p = 13;                          // p在子类Child2中被赋值为13

               c2 = 13;

      }

};

class GrandChild : public Child1, public Child2

{

public:

      int grandchild;

      // p显然也存在于GrandChild中,但是到底是12,还是13呢?这就产生了二义性

      inline GrandChild()

      {

               grandchild = 14;

      }

 };

 

int main(void)

{

      GrandChild* pGC = new GrandChild();

      cout << pGC->p << endl;

      return 0;

}

 

上面程序是不能通过编译的,编译器输出的错误信息如下:

…: error C2385: 'GrandChild::p' is ambiguous

…: warning C4385: could be the 'p' in base 'Parent' of base 'Child1' of class 'GrandChild'

…: warning C4385: or the 'p' in base 'Parent' of base 'Child2' of class 'GrandChild'

正如编译器告诉我们的那样,GrandChild::p是模棱两可,它被Child1继承了即Child1中包含了一个Parent subobject,也被Child2继承了即Child2中也包含了一个Parent suboject,然后GrandChild又同时继承了Child1和Child2,根据“derived class中要保持base class的完整原样性原则”,因此GrandChild包含了两个ParentObject。所以当pGC->p时,编译器根本无法确定是调用Child1::p还是Child2::p,由此边产生了模棱两可的情形。怎么解决这样的问题呢?答案就是用虚继承或者叫虚基类的方式。

 

在上面的示例程序中做如下改动:

class Child1 : public Parent       ->     class Child1 : virtual public Parent

class Child2 : public Parent      ->      class Child2 : virtual public Parent

GrandChild的定义维持不变:

class GrandChild : public Child1, public Child2

 

做了上述改动后,即增加了两个virtual关键字,再编译就不会出现ambiguous之类的错误了。这是因为加上了virtual关键字后,就可以保证Parent suboject在GrandChild中只存在一份,从而消除了ambiguity。上面修改后的程序运行结果是13,这说明Child2类的那个p起了作用,如果GrandChild的定义写成:

     class GrandChild : public Child2, public Child1

那么运行结果将是12。

上面的试验结果表面,在多重继承的时候,如果父类中有同名的成员变量(类似这篇文章中谈及的例子),为了防止二义性,一般要采用虚继承的方式,并且最右边的基类中的那个成员变量会出现在派生类对象中。

总结因果关系:多重继承—>二义性—>虚继承解决

内容概要:本文详细介绍了由中国某顶尖科技公司推出的专注于通用人工智能的应用工具DeepSeek。首先是入门篇,阐述了DeepSeek的基本介绍、所需前期准备工作以及具体的使用步骤,指导使用者如何正确提问以获取最佳效果;然后是进阶部分,深入探讨各种实用功能的操作,如三种模式间的转换、文件处理能力、多语言翻译、温度参数设定和提示语的设计方法等内容;最终到达精通层面,展示了一系列应用场景,包括但不限于协助撰写学术论文、助力自媒体创作、构建个人学习计划及编程协助等方面的具体实施,并讲解了一些高阶技巧,比如思维链开放机制、创建专属领域内训练好的自定义AI模型,还有结合其他生产力软件提升工作效率的方法。同时提及如何利用多轮连续交互的方式解决更加错综复杂的问题。 适用人群:面向对DeepSeek这款AI工具感兴趣的开发者、研究员或是寻求提升工作效率的专业人士。 使用场景及目标:适用于初次接触DeepSeek的新手,希望通过循序渐进的学习路径来逐步掌握这个强大的工具;也为有经验用户提供更广泛的想象空间和技术支持,以充分发挥DeepSeek的价值并促进工作流优化。对于研究人员和教育工作者来说,它也可以成为科研助手和教学资源。 其他说明:该工具不仅局限于单一领域的使用,在多个方面均有涉猎并展现出色的表现力。无论您身处哪个行业,都可以基于自身需求发掘出DeepSeek更多的潜力所在。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值