2017-02-19 24 views
2

最有可能的一個不希望這個樣本編譯:「靜態成員函數將覆蓋基類的虛擬功能」通過gcc和鏗鏘而陷入沒有VC++

#include <iostream> 

class C { 
public: 
    virtual void Foo() { 
     std::cout << "From C\n"; 
    } 
}; 

class D : public C { 
public: 
    static void Foo() { 
     std::cout << "From D\n"; 
    } 
}; 

int main() { 
    D d; 
    d.Foo(); 
    return 0; 
} 

它不會在GCC的確編譯clang(錯誤「靜態成員函數覆蓋基類中的虛函數」)。但是,它確實在Visual C++中編譯,發出從D到運行控制檯。即使使用帶有選項ISO C++最新草案標準(/ std:C++ latest)的最新VC++ RC 2017編譯器(v141)/permissive-link)開啓。

哪個編譯器是正確的?這是標準的錯誤嗎?如果是這樣,這是否意味着VC++在這種情況下不遵循標準?

+1

我相當確定這是違法的。最有可能是一個MSVC錯誤。此外,編譯器版本通常是MSVC14.1或更具體的19.10.24930在我的安裝。 – tambre

回答

3

這絕對是一個MSVC錯誤。 ISO C++不允許這樣做。

class.static.mfct/2(重點煤礦):

[注:靜態成員函數沒有this指針。 - 結束註釋]靜態成員函數不應該是虛擬的。 有 不得是靜態和相同 名稱和相同的參數類型的非靜態成員函數([over.load]) ...

+1

「不合格」並不意味着「不應該編譯」。語言定義要求編譯器發佈診斷。我在這裏沒有提到這個代碼是否會發生這種情況。 –

+0

@PeteBecker,注意到;並更正。謝謝。 :-)。我仍然學習用這些標準術語來迂迴。 – WhiZTiM

+0

您的重點關注重載,但'C :: Foo'不參與重載,在獨立的作用域中,除非在'D'中引用'using C :: Foo;'。如果'C :: Foo'不是虛擬的,'static D :: Foo'就會隱藏它。 – w1ck3dg0ph3r

1

10.3:2指出D::Foo必須是虛擬的(即使沒有聲明)。

如果虛擬成員函數VF在類Base和在 類派生的,直接或間接地從基地成員 函數VF具有相同名稱,參數類型列表(8.3衍生聲明。 5), cv-qualification和ref-qualifier(或缺少相同)聲明爲Base :: vf ,則Derived :: vf也是虛擬的(無論它是否聲明如此 )並且它會覆蓋111 Base :: VF ...

而且9.4.1:2個狀態,它不能是六rtual

[注意:一個靜態成員函數沒有這個指針(9.3.2)。 -end note]一個靜態成員函數不應該是虛擬的。 不應該是一個靜態和非靜態的成員函數,其名稱相同,其名稱相同,參數類型相同(13.1)。不會將靜態成員函數 聲明爲const,volatile或const volatile。

相關問題