在C ++中,基类是否可以在所有派生类中拨入虚拟方法?

时间:2010-06-04 12:45:48

标签: c++ virtual design-patterns derived

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

新来者经常对系统造成的错误是在某处引入虚拟方法。这可以保证系统崩溃,因为无法确保VT(虚拟表)驻留在每个进程的同一地址。

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

7 个答案:

答案 0 :(得分:4)

在提交到您的存储库时,
对于以这种方式共享的每个班级,
如果虚拟词出现在文件中 没有提交,发送电子邮件给高级开发人员,并停止违规方的工资。

答案 1 :(得分:4)

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

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

答案 2 :(得分:3)

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

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

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则引发错误。

答案 3 :(得分:2)

要检查班级是否有虚拟方法,您可以使用boost::is_polymorphic

答案 4 :(得分: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 );
}

答案 5 :(得分:1)

你可以#define virtual Something_else当任何人使用虚拟时会出现编译器错误,但如果没有更多工作就没有任何意义。

答案 6 :(得分: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.");