2

我们系统的一部分使用在不共享共同祖先的进程之间共享的内存。我们将 C++ 对象放在这个共享内存中。这些对象上的方法要么在标题中内联,要么在链接到相应进程的对象库中外联。

系统新手经常犯的一个错误是在某处引入虚拟方法。这保证会导致系统崩溃,因为无法确保 VT(虚拟表)驻留在每个进程中的相同地址。

因此,我想知道如果有人试图引入虚拟方法,我是否有办法让编译器发出错误。类似于将复制和赋值构造函数设为私有以禁止复制语义。

4

7 回答 7

4

在提交到您的存储库时,
对于以这种方式共享的每个类,
如果文件中出现虚拟单词,则
提交失败,请向高级开发人员发送电子邮件,并扣减违规方的工资。

于 2010-06-04T13:38:08.270 回答
4

当虚函数出现在具有非虚析构函数的类中时,GCC(可能是其他人)会发出警告。

给所有共享类一个显式的非虚拟析构函数(什么都不做?),并将警告视为错误。

于 2010-06-04T13:52:23.777 回答
3

Boost.TypeTraits 提供了一个is_polymorphic特征,但你可能需要做一些技巧才能让它在任何需要的地方应用。(例如,调用is_polymorphic基类不会告诉您派生类是否引入了虚函数。)

根据您的构建系统和可用工具,您可以在那里引入检查。例如,如果我nm -C在一个由 GCC 创建的目标文件上运行,我会看到一个带有虚函数的简单测试类的以下输出:

0000000e T TestMe::TestMe()
00000078 T TestMe::~TestMe()
00000000 V typeinfo for TestMe
00000000 V typeinfo name for TestMe
00000000 V vtable for TestMe

因此,我可以设置我的 makefile(或其他)以nm -C在所有目标文件上运行,并在包含vtable for.

于 2010-06-04T13:06:58.463 回答
2

要检查类是否具有虚拟方法,您可以使用boost::is_polymorphic.

于 2010-06-04T12:59:20.470 回答
2

当有人向类添加虚函数时,您可以使用is_polymorphicBOOST_STATIC_ASSERT组合来创建编译器错误。将 BOOST_STATIC_ASSERT 调用放入类的实现文件中。

#include <boost/type_traits/is_polymorphic.hpp>
#include <boost/static_assert.hpp>
#include <cassert>

class A
{
public:
    /*virtual*/ void magic() {};    // making this virtual causes a compile error and a runtime error
};

using namespace boost;
int main()
{
    assert( is_polymorphic<A>::value == false );
    BOOST_STATIC_ASSERT( is_polymorphic<A>::value == false );
}
于 2010-06-04T14:37:59.570 回答
1

当任何人使用 virtual 时,您可能#define virtual Something_else会给出编译器错误,但如果没有更多的工作,它们就没有任何意义。

于 2010-06-04T13:01:37.573 回答
0

这是 (Visual Studio 2015) C++11 对一个老问题的回答。它类似于 Boost 答案。

#include <type_traits>

class foo
{
};

static_assert(!std::is_polymorphic<foo>::value, "Virtual not allowed in this class.");
于 2016-01-28T22:57:07.213 回答