没有虚拟继承的多重继承

时间:2014-08-19 06:35:43

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

我想了解多重继承,这是我的代码:

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()函数,编译器也会抱怨,甚至声明为静态。为什么?

3 个答案:

答案 0 :(得分:10)

含糊不清是什么意思?

如果编译器在给定上下文时无法决定调用哪个函数,则会抱怨模糊调用。因此,为了理解投诉,您必须检查可能存在的含糊之处。

  

为什么编译器抱怨对static()的非静态版本的模糊调用,同时满足静态版本?

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

钻石继承的问题不在于编译器不知道要执行哪个代码,而是它不知道要提供哪个this(有A个对象中的两个D,其中一个包含在B中,另一个包含在C中。

当您使用static A函数时,没有传递隐式this,因此没有问题;如果您尝试使用非static函数,则编译器无法确定this是否应指向AB中的C,它& #39;暧昧。

  

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

此时,编译器可以在B::increment()C::increment()之间进行选择,它应该选择哪个?它含糊不清。

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

注意:即使B未实现increment,自A起,您也可以致电B::increment()实际调用A::increment()C也是如此。

答案 1 :(得分:9)

  1. 它被称为钻石继承问题。你有两个派生自A的类。然后派生自两个类。你有两个版本的非静态void increment()。有了静态,你就有了。
  2. 因为你可以,但绝不应该覆盖非虚函数,也许你的编译器是严格的或严格的模式。
  3. 钻石继承:http://www.parashift.com/c++-faq/mi-diamond.html 隐藏功能:http://www.parashift.com/c++-faq/hiding-inherited-public.html

答案 2 :(得分:2)

本声明:

struct D : public B, C {};

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