Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么GCC会给我一个错误:没有唯一的最终重写器?_C++_Gcc_Diamond Problem - Fatal编程技术网

C++ 为什么GCC会给我一个错误:没有唯一的最终重写器?

C++ 为什么GCC会给我一个错误:没有唯一的最终重写器?,c++,gcc,diamond-problem,C++,Gcc,Diamond Problem,在下面的代码中,我得到以下警告和错误: test.cpp:15: warning: direct base 'B' inaccessible in 'D' due to ambiguity test.cpp:15: error: no unique final overrider for 'virtual void A::f()' in 'D' 但是如果我从A中删除B的虚拟继承(即结构B:public A),我只得到警告,没有错误 struct A { virtual void f() =

在下面的代码中,我得到以下警告和错误:

test.cpp:15: warning: direct base 'B' inaccessible in 'D' due to ambiguity
test.cpp:15: error: no unique final overrider for 'virtual void A::f()' in 'D'
但是如果我从A中删除B的虚拟继承(即
结构B:public A
),我只得到警告,没有错误

struct A
{
  virtual void f() = 0;
};

struct B : public virtual A
{
  void f() {}
};

class C : public B
{};

struct D : public C, virtual B
{};

int main()
{
  return 0;
}

为什么??这是可怕的钻石吗?

这是因为
C
以非虚拟方式从
B
继承,而
D
以虚拟方式从
B
继承。这将为您提供两次
B
,包括两次
f()

尝试在
C
中虚拟继承
B

更新:那么,当您从
A
中删除
B
中的虚拟继承时,为什么它会起作用呢?因为它更改了“最终重写器”。如果没有
B
中的
A
C
中的
B
中的
A
两次:一次在
C
中(最后覆盖
B
中的
f()
),一次在
D
中的
B
中的虚拟
B
中(最后覆盖
f()
)。如果将
B
中的虚拟继承添加回
A
A
将只出现一次,并且将有两个最终覆盖竞争实现
A
中的纯
f()
,都在
B
中,一个从
C
中,一个从虚拟
B

作为一种解决方法,您可以使用
向D添加一个
,即使用C::f添加
使用B::f


<参见C++ +33/2

让我们看看“最终重写器”的定义,从<代码> 10.3 [类.Virtual] / 2

类对象
S
的虚拟成员函数
C::vf
是最终重写器,除非
S
的最派生类是基类子对象(如果有)声明或继承另一个重写
vf
的成员函数

在派生类中,如果基类子对象的虚拟成员函数具有多个最终重写器,则程序格式错误

对于A的虚拟继承,只有一个类型为A的基类子对象,其虚拟成员函数f()具有多个最终重写器(类型为B的每个子对象中有一个)


如果没有来自A的虚拟继承,则有两个不同类型A的基类子对象,它们的虚拟成员函数f()都有自己的最终重写器(每个B子对象中有一个)

虚拟基子对象在完整对象中的所有基子对象之间“共享”。由于A在D::C::B和D::B之间共享,因此它无法判断哪个B对象应该调用其
f()
作为
A::f()的覆盖。

考虑:

#include <iostream>

struct A {
  virtual void f() = 0;
  virtual ~A() {}
};

struct B : virtual A
{
  void f() { std::cout << "B\n"; }
};

struct C : virtual A
{
  void f() { std::cout << "C\n"; }
};

struct D : C, B {};

int main() {
  D d;
  A *a = dynamic_cast<A*>(&d); // single shared A between B and C
  a->f(); // Should B::f() be called, or C::f()?
}

实际上从B继承C的可能的重复确实解决了这个问题。但是我仍然不明白为什么从A中删除B的虚拟继承会影响结果。@Rai如果你从
B
中虚拟继承,那么你就不再需要从
A
中虚拟继承了。是的,我相信这是真的。但是它仍然不能回答为什么当B不再从A继承时错误会消失的问题。@Rai好的,现在我知道你是从哪里来的了。请看我的更新。啊,现在我明白了,非常感谢。你和库比差不多在同一时间拿到的,不用投了。您可以显式消除歧义:
d.A::f()
#include <iostream>

struct A {
  virtual void f() = 0;
  virtual ~A() {}
};

struct B : A
{
  void f() { std::cout << "B\n"; }
};

struct C : A
{
  void f() { std::cout << "C\n"; }
};

struct D : C, B {};

int main() {
  D d;
  // two different A objects
  A *a1 = static_cast<A*>(static_cast<B*>(&d));
  A *a2 =  static_cast<A*>(static_cast<C*>(&d));
  a1->f();
  a2->f();
}