gpt4 book ai didi

c++ - Diamond 层次结构中的虚函数重载在 clang 和 gcc 中产生不同的结果

转载 作者:行者123 更新时间:2023-12-02 08:36:34 25 4
gpt4 key购买 nike

以下代码在 clang 上产生不同的结果。

#include <iostream>

struct Dummy1 {};
struct Dummy2 {};

struct A {
virtual void foo(Dummy1) {
std::cout << "A" << std::endl;
}
virtual void foo(Dummy2) {
std::cout << "A" << std::endl;
}
};


template<class T>
struct C : virtual A {
using A::foo;
void foo(Dummy2) override {
std::cout << "C" << std::endl;
}
};


template<class T>
struct B : virtual A {
using A::foo;
void foo(Dummy1) final {
std::cout << "B" << std::endl;
}
};

template<class T>
struct D : B<T>, C<T> {
// using B<T>::foo; // error: call to member function 'foo' is ambiguous
// using C<T>::foo; // error: call to member function 'foo' is ambiguous
using A::foo;
};


int main() {
D<int> d;
d.foo(Dummy1{});
d.foo(Dummy2{});

A& a = d;
a.foo(Dummy1{});
a.foo(Dummy2{});

B<int>& b = d;
b.foo(Dummy1{});
b.foo(Dummy2{});


C<int>& c =d;
c.foo(Dummy1{});
c.foo(Dummy2{});

return 0;
}

gcc(版本 4.8.1 - 9.1)、icc(版本 16、17、19)、Visual Studio 2017 15.4.0 Preview 1.0、Visual Studio 2013 12.0.31101.00 Update 4、clang(版本 3.4.1 - 3.9)。 1)

所有输出都给出以下输出,这是我所期望的:

B
C
B
C
B
C
B
C

仅限方法 C<T>::foo(Dummy1)B<T>::foo(Dummy2)已选择,方法A<T>::foo没有使用。

Clang(版本 4.0.0 - 8.0.0)选择 A::foo(Dummy2)当通过 D<T> 调用电话时对象,然后才可以。当通过引用 B<T> 调用时-C<T>::foo(Dummy2)已选择。

B
A <-- difference
B
C
B
C
B
C

当派生类的顺序更改为struct D : C<T>, B<T>时,然后输出更改为:

A <--
C
B
C
B
C
B
C

似乎对于第二个派生类方法 foo不被视为虚拟。

只有 Visual Studio 发出警告,但没有多大帮助 C4250 .

写作 using B<T>::foo;using C<T>::foo;D<T>而不是using A::foo;使 clang 产生以下错误:

error: call to member function 'foo' is ambiguous

在 gcc 上行为不会改变,代码编译和输出是相同的。

这里的正确行为是什么?

由于应用程序给出了不同的结果,有没有办法找到此构造的所有相似实例或做出一些解决方法?我必须使用 gcc 和 clang 进行编译。检查是否存在比我发现的更多地方相同的问题可能很困难。

最佳答案

我相信这里发生了两件事。

首先,clang 的实现肯定存在问题,因此提交错误报告是一个很好的举措。

但是当您在 D 引用上调用 foo 时也会出现问题

D<int> d;
d.foo(Dummy1{});
d.foo(Dummy2{});

Visual Studio 给您的警告实际上非常准确:从技术上讲,每次调用都有两个选项,但通过主导选择一个选项。

对于 Dummy1 重载,B 类中有被重写的实现,但 C 类也有未重写的实现/。这就是警告中所说的“主导”一方隐藏另一方的情况。在这种情况下,主导版本是类 B 中的重写版本,而弱版本是类 C 中的版本。如果您也覆盖了 C 类中的 Dummy1 重载,则会出现不明确的调用。

对于 Dummy2 重载来说也是如此。

因此,编译器警告您的是,在已知的 D 实例的情况下,您实际上有一个选择,并且应该明确说明它。

关于c++ - Diamond 层次结构中的虚函数重载在 clang 和 gcc 中产生不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56452518/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com