相同的程序行为在 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 的实现方式的细节。
我正在阅读 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 的实现方式的细节。