相同的程序行为在 g++ 和 MSVS 2010 中不同

Same program behavior is different in g++ & MSVS 2010

我正在阅读 this。链接问题的接受答案包含以下代码:

class Base
 {
    private:
        virtual ~Base() = 0;   /* A */
 };

 class Derived : protected virtual Base
 {
    private:
     ~Derived () {.......}    /* B */
 };

我在 g++ 4.8.1、4.9.2 和 MSVS 2010 编译器中尝试了这个程序(参见实时演示 here.)。但是 g++ 4.8.1 & 4.9.2 给我一个编译器错误,而 MSVS 2010 编译它没有任何错误。 Clang 也给出了一个错误见 here.

那么,为什么 g++ 显示错误消息?我还没有创建 derived class 的对象。所以,我认为它不应该给出编译错误 & MSVS 2010 是正确的。

但是为什么这两个编译器的行为不同?

关于此程序的行为,哪个编译器是正确的?这是这些编译器中的任何一个或其他编译器中的错误吗?

我确实有点糊涂了

非常感谢您的帮助。

如果基本析构函数是私有的,它将无法删除继承的实例。就那么简单。但是,这不是标准化的。

对我来说,这看起来像是在 VS2010 中编译,只是因为从未使用过 class 'Derived'。我在 VS2012 中尝试过同样的方法。如果您要在 VS2012 中使用 class,编译也会失败:

class Base
{
    virtual ~Base()=0;      /* A */
};
Base::~Base() { }

class Derived : protected virtual Base
{
  ~Derived()                    /* B */
  { }
};

int main() 
{
  Derived derived;
}   

错误消息是:

1>c:\repositories\teststrongvirtualdestructor\teststrongvirtualdestructor\teststrongvirtualdestructor.cpp(20): error C2248: 'Derived::__vbaseDtor' : cannot access private member declared in class 'Derived'
1>          c:\repositories\teststrongvirtualdestructor\teststrongvirtualdestructor\teststrongvirtualdestructor.cpp(14) : compiler has generated 'Derived::__vbaseDtor' here
1>          c:\repositories\teststrongvirtualdestructor\teststrongvirtualdestructor\teststrongvirtualdestructor.cpp(12) : see declaration of 'Derived'
1>
1>Build FAILED.

我认为 g++ 和 clang(以及 VS2012)是正确的。而且那个 VS2010 是不正确的。

本质上,要析构 Derived 的实例,编译器必须确定 Base 的析构函数是否可访问。派生的 class 无法访问基 class 的 private 析构函数,因此无法析构 Derived

我建议这不需要实例化 class。在 "separate compilation" 模型下,编译器必须假定一些其他编译单元(在编译 this 编译单元时对编译器不可见)将实例化 and/or 销毁的实例class。这意味着它应该 check/compile/emit 在每个编译单元中为析构函数编写代码,该单元可以看到该析构函数的定义。

与 "separate compilation" 模型相关的规则被非正式地称为 "as if" 规则 - 实现必须 就好像 它遵循每个规则,即使如果它在引擎盖下做的事情不同。

事实是,各种 "as if" 规则是编译器供应商经常走捷径的地方 - 为了编译速度或其他目的。

这只是 VS2010 出错原因的一种可能解释。

结果是 VS2010 在这种情况下没有正确检查析构函数的可访问性。较旧的 Microsoft C++ 编译器因不完全符合标准而臭名昭著。近年来,微软一直在战略性地寻求提高他们对标准的符合性,但这些事情要被淘汰还需要时间。这与 VS2010 不会抱怨,但 VS2012(像其他编译器一样)会抱怨的观察结果是一致的。

一个可能的解释是VS2010不完全符合"separate compilation"的要求。另一个是在检查 base classes 中私有成员的可访问性时只是走捷径。要确定这些解释中的任何一个 - 或者其他 - 是否是解释,可能有必要深入了解 VS2010 的实现方式的细节。