【问题标题】:multiple inheritance without virtual inheritance没有虚拟继承的多重继承
【发布时间】:2014-10-12 04:15:12
【问题描述】:

我正在尝试理解多重继承,这是我的代码:

struct A {
  A() {}
  static int n;
  static int increment() { return ++n; }
};
int A::n = 0;

struct B : public A {};
struct C : public A {};
struct D : public B, C {};

int main() {
  D d;
  cout<<d.increment()<<endl;
  cout<<d.increment()<<endl;
}

此代码有效。但是,如果我将 increment() 更改为非静态,它将失败。

我的问题:

  1. 为什么编译器抱怨非静态版本 increment() 的调用模棱两可,而静态版本却满足?
  2. 如果我在 B 或 C 中添加另一个 increment() 函数,编译器也会报错,甚至声明为静态。为什么?

【问题讨论】:

标签: c++ inheritance multiple-inheritance virtual-inheritance


【解决方案1】:

模棱两可是什么意思?

当编译器无法根据上下文决定调用哪个函数时,它会抱怨不明确的调用。因此,为了了解投诉,您必须检查可能存在的歧义。

为什么编译器抱怨非静态版本的增量()调用模棱两可,而静态版本却满足?

根据定义,一个类的static 函数不依赖于该类的任何实例。您可以将其称为A::increment()(请参阅,没有实例)这一事实强调了这一点。

菱形继承的问题不是编译器不知道要执行哪个代码,而是不知道要提供哪个this(你的里面有两个A D 对象,一个包含在B 中,一个包含在C 中)。

当你使用Astatic函数时,没有隐式传递this,所以没有问题;如果您尝试使用非static 函数,则编译器无法确定this 是否应该指向BC 中的A,这是不明确的。

如果我向 B 或 C 添加另一个 increment() 函数,编译器也会报错,甚至声明为静态。为什么?

此时,编译器可能会在B::increment()C::increment() 之间进行选择,它应该选择哪个?模棱两可。

当你有一个线性层次结构时,它会调用“最接近”的层次(将那些隐藏在继承树的更下方),但这里 BC 是两个独立的分支,没有“更好”的分支.

注意:即使B 没有实现increment,因为A 你可以调用B::increment(),它实际上调用了A::increment()C 也是如此。

【讨论】:

    【解决方案2】:
    1. 称为菱形继承问题。您有两个类,它们是从 A 派生的。然后是从两个派生的类。您有两个版本的非静态 void increment()。有了静态,你就有了。
    2. 因为您可以,但绝不应该覆盖非虚函数,而且您的编译器可能是严格的或处于严格模式的。

    钻石继承:http://www.parashift.com/c++-faq/mi-diamond.html 隐藏功能:http://www.parashift.com/c++-faq/hiding-inherited-public.html

    【讨论】:

      【解决方案3】:

      此声明:

      struct D : public B, C {};
      

      将创建两个A 实例。编译器需要知道您打算从 哪个 实例调用该方法。 static 函数只不过是一个全局函数,它是类的朋友——当调用者意图调用它时,唯一的要求是完全限定的名称。静态不会在继承中发挥任何作用。

      【讨论】:

        猜你喜欢
        • 2017-03-31
        • 1970-01-01
        • 1970-01-01
        • 2015-11-21
        • 2013-11-19
        • 1970-01-01
        • 2011-10-15
        • 1970-01-01
        • 2014-11-06
        相关资源
        最近更新 更多