8

我正在使用googlemockstd::fstream在我的单元测试中模拟一个对象,如下所示:

TEST_F(SomeTest, SomethingIsDoneCorrectly)
{
    class MockFstream : public std::fstream {};
    MockFstream lMockFstream;
    // Expectations and assertions here
}

当我编译时,我收到以下警告:

警告 1 警告 C4250: 'SomeTest_SomethingIsDoneCorrectly_Test::TestBody::MockFstream' : 通过支配继承 'std::basic_istream<_Elem,_Traits>::std::basic_istream<_Elem,_Traits>::_Add_vtordisp1'

警告 2 警告 C4250: 'SomeTest_SomethingIsDoneCorrectly_Test::TestBody::MockFstream' : 通过支配继承 'std::basic_ostream<_Elem,_Traits>::std::basic_ostream<_Elem,_Traits>::_Add_vtordisp2'

我更喜欢干净的构建输出,所以我想抑制这些特定的警告,但我正在编写跨平台代码,所以我也更喜欢避免特定于编译器的#pragmas.

我可以在 googlemock 对象中做些什么来隐藏这些警告吗?

4

1 回答 1

8

事实证明,这些警告是 Microsoft C++ STL 中某些怪癖的副作用。我在下面引用了相关 Microsoft Connect 问题的解释。

我的解决方案只是在我的模拟中实现继承函数的空版本:

TEST_F(SomeTest, SomethingIsDoneCorrectly)
{
    class MockFstream : public std::fstream
    {
        void _Add_vtordisp1() { } // Required to avoid VC++ warning C4250
        void _Add_vtordisp2() { } // Required to avoid VC++ warning C4250
    };
    MockFstream lMockFstream;
    // Expectations and assertions here
}

Microsoft对警告发生原因的解释:

这里的故事有些复杂。VC 有一个晦涩难懂的编译器选项 /vd2(记录在http://msdn.microsoft.com/en-us/library/7sf3txa8.aspx),它修复了涉及虚拟基类的晦涩错误。默认情况下,VC 会做一些稍微不符合 C++ 标准的事情。/vd2 将 VC 的行为更改为一致,但这本质上会影响类布局。(这种布局差异是为什么默认值没有更改为一致的原因 - 这会破坏用户尝试混合使用不同主要版本的 VC 编译的代码。我们的 C++ 标准库实现禁止这种混合,但编译器本身更宽松一些.) 因此,如果用户想要 /vd2,他们必须以这种方式编译所有内容。

扭曲是布局错误(/vd2 修复)影响使用虚拟基类的 iostreams,而我们的 iostreams 实现有一个单独编译的组件(在 msvcp100.dll/libcpmt.lib/等中)。当 MS 构建 STL 的 DLL/LIB 时,它们以默认方式编译,没有 /vd2。结果,使用 /vd2 的人不能使用 iostreams,否则他们会遇到奇怪的崩溃。呸。

因此,我们添加了无操作虚函数 _Add_vtordisp1() 和 _Add_vtordisp2()。它们的存在使 VC 完全一致地执行布局,无论是否使用 /vd2,因此使 iostreams 可以双向使用。

_Add_vtordisp1() 和 _Add_vtordisp2() 触发警告 C4250,谈论优势。这个警告实际上是完全没用的——它是说编译器将完全按照标准要求它做的事情。因此,我们在 STL 的标头中抑制它(必须是 /W4 /analyze clean)。如果您是从 fstream 派生的,则需要在您自己的代码中禁止显示此警告。

于 2013-01-23T18:56:10.637 回答