代码之家  ›  专栏  ›  技术社区  ›  Deqing

无虚拟继承的多重继承

  •  11
  • Deqing  · 技术社区  · 10 年前

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

    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. 为什么编译器抱怨非静态版本的调用不明确 增量() ,而满足于静态的?
    2. 如果我再加一个 增量() 函数转换为B或C,编译器也会抱怨,甚至声明为静态。为什么?
    3 回复  |  直到 10 年前
        1
  •  10
  •   Matthieu M.    10 年前

    暧昧是什么意思?

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

    为什么编译器对increment()的非静态版本的调用不明确,而对静态版本的则满意?

    根据定义 static 类的函数不依赖于类的任何实例。你可以称之为 A::increment() (参见,无实例)。

    菱形继承的问题并不在于编译器不知道 密码 执行,就是不知道 this 提供(有两个 A 在您的 D 对象,一个包含在 B 还有一个 C ).

    当您使用 静止的 功能 A. ,无隐式 通过,因此没有问题;如果您尝试使用非- 静止的 函数,则编译器无法决定 应指向 A. 在里面 B 或在 C ,这是模棱两可的。

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

    此时,编译器可以在 B::increment() C::increment() ,它应该选择哪个?这是模棱两可的。

    当您有一个线性层次结构时,它会调用与其“最近”的层次结构(这会隐藏继承树下面的层次结构),但这里 B C 是两个独立的分支,没有“更好”的分支。

    注:即使 B 不执行 increment 自从 A. 你能打电话吗 B: :increment() 它实际上调用 A: :increment() 。同样的道理 C .

        2
  •  9
  •   DoctorMoisha    10 年前
    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
  •  2
  •   Ajay    10 年前

    本声明:

    struct D : public B, C {};
    

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