[英]Virtual function overloading in diamond hierarchy produces different results in clang and gcc
以下代碼在 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)。
全部給出以下輸出,這是我所期望的:
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)在通過D<T>
對象調用時選擇A::foo(Dummy2)
,然后才選擇。 當通過引用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 B<T>::foo;
並using C<T>::foo;
在D<T>
而不是using A::foo;
使 clang 產生以下錯誤:
錯誤:對成員函數“foo”的調用不明確
在 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
實例的情況下,你實際上有一個選擇,應該明確地說明它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.