我们系统的一部分使用在不共享共同祖先的进程之间共享的内存。我们将 C++ 对象放在这个共享内存中。这些对象上的方法要么在标题中内联,要么在链接到相应进程的对象库中外联。
系统新手经常犯的一个错误是在某处引入虚拟方法。这保证会导致系统崩溃,因为无法确保 VT(虚拟表)驻留在每个进程中的相同地址。
因此,我想知道如果有人试图引入虚拟方法,我是否有办法让编译器发出错误。类似于将复制和赋值构造函数设为私有以禁止复制语义。
我们系统的一部分使用在不共享共同祖先的进程之间共享的内存。我们将 C++ 对象放在这个共享内存中。这些对象上的方法要么在标题中内联,要么在链接到相应进程的对象库中外联。
系统新手经常犯的一个错误是在某处引入虚拟方法。这保证会导致系统崩溃,因为无法确保 VT(虚拟表)驻留在每个进程中的相同地址。
因此,我想知道如果有人试图引入虚拟方法,我是否有办法让编译器发出错误。类似于将复制和赋值构造函数设为私有以禁止复制语义。
在提交到您的存储库时,
对于以这种方式共享的每个类,
如果文件中出现虚拟单词,则
提交失败,请向高级开发人员发送电子邮件,并扣减违规方的工资。
当虚函数出现在具有非虚析构函数的类中时,GCC(可能是其他人)会发出警告。
给所有共享类一个显式的非虚拟析构函数(什么都不做?),并将警告视为错误。
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
.
要检查类是否具有虚拟方法,您可以使用boost::is_polymorphic
.
当有人向类添加虚函数时,您可以使用is_polymorphic与BOOST_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 );
}
当任何人使用 virtual 时,您可能#define virtual Something_else
会给出编译器错误,但如果没有更多的工作,它们就没有任何意义。
这是 (Visual Studio 2015) C++11 对一个老问题的回答。它类似于 Boost 答案。
#include <type_traits>
class foo
{
};
static_assert(!std::is_polymorphic<foo>::value, "Virtual not allowed in this class.");