2017-02-19 39 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。