【问题标题】:Adding virtual removes the error : type 'base' is not a direct base of derived class添加虚拟消除了错误:类型'base'不是派生类的直接基础
【发布时间】:2012-01-15 04:32:00
【问题描述】:

考虑下面的示例代码:

#include <iostream>

using namespace std;

class base
{
   public:
      base()
      {
         cout << "ctor in base class\n";
      }
};

class derived1 : public base
{
   public:
      derived1()
      {
         cout <<"ctor in derived1 class\n";
      }
};

class derived2 : public derived1
{
   public:
      derived2() : base()
      {
         cout << "ctor in derived2 class\n";
      }
};

int main()
{
   derived2 d2obj;
   return 0;
}

这给出了错误:

错误:类型 `base' 不是 `derived2' 的直接基类

为什么会出现这个错误?如果我将基类设为虚拟,则错误不再存在。这是什么原因?

【问题讨论】:

  • 不应该derived2() : base()derived2() : derived1()? derived2 不从 base 继承。
  • 不是这样,derived2 也继承自 base,因为它继承自 derived1。实际上,derived2 对象包含 derived1 对象和基础对象。
  • 抱歉它没有直接继承自base
  • 是的,我同意,它不直接继承。所以你不能直截了当地说derived2 doesn't inherit from base。谢谢指正:)

标签: c++ inheritance derived-class base-class


【解决方案1】:

因为base 不是derived2 的直接基础。您必须为您的直接基础提供一个构造函数,在这种情况下为derived1

虚拟基地是个例外。它们总是在叶类中初始化,否则可能会为同一个基类调用多个构造函数。所以如果你把base设为虚拟,不仅可以在derived2中初始化,还必须。

当您的派生图不是树时,就会出现问题。 IBM 有一张漂亮的照片。如果您不使基础(示例中为V)虚拟(无处不在),您将拥有多个副本。如果你确实让它到处都是虚拟的,你只会有一个副本,但是直接的孩子不能运行构造函数(它将运行> 1次)并且叶子类必须。更多详情,最好在网上搜索。

【讨论】:

  • 谢谢 smparkes。我期待这个答案。但是您能否在Virtual bases are the exception 上多解释一下
  • 很难,在 600 个字符之内,恐怕。当您有一个不是树的派生图时,就会出现问题。 publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/… 有一张漂亮的照片。如果您不将基础(示例中的 V)虚拟化(无处不在),您将拥有多个副本。如果你确实让它到处都是虚拟的,你只会有一个副本,但是直接的孩子不能运行构造函数(它将运行> 1次)并且叶子类必须。更多详情,最好在网上搜索。
  • @smparkes:不要在 600 个字符的限制评论中扩展答案,也许您应该扩展答案? :D
  • @MooingDuck,谢谢。猜我是在发泄。虚拟基地是如此的焦油宝贝,我想我(下意识地)想要 600 个字符的限制。
【解决方案2】:

改变

class derived2 : public derived1
{
   public:
      derived2() : base()
      {
         cout << "ctor in derived2 class\n";
      }
};

class derived2 : public derived1
{
   public:
      derived2() : derived1()
      {
         cout << "ctor in derived2 class\n";
      }
};

这是因为您试图从孙子 derived2 调用 base1 构造函数。

If you change the derivation of derived1 from base1 to be virtual. It is ok to call base1 from derived2. More details here.

【讨论】:

  • 我明白这一点。但是您能解释一下为什么在将基类设为虚拟时错误不再存在吗?
【解决方案3】:

你在两者之间派生了1​​。您只能在初始化列表中调用直系父母

【讨论】:

    猜你喜欢
    • 2018-03-18
    • 1970-01-01
    • 2019-11-04
    • 1970-01-01
    • 2021-04-14
    • 2020-09-30
    • 2021-04-15
    • 2017-11-15
    • 2013-08-31
    相关资源
    最近更新 更多