views:

164

answers:

6

Part of our system uses memory shared between processes who do not share a common ancestor. We place C++ objects in this shared memory. Methods on these objects are either inline in the headers or out of line in object libraries that get linked into the respective processes.

An error frequently made by new comers to the system is to introduce a virtual method somewhere. This is guaranteed to crash the system as there is no way to ensure that the VT (virtual table) resides at the same address in each process.

Thus I wonder whether there is a way for me to cause the compiler to issue an error if someone attempts to introduce a virtual method. Something similar to making the copy and assignment constructors private to disallow copy semantics.

+2  A: 

To check whether class has a virtual method you could use boost::is_polymorphic.

Kirill V. Lyadvinsky
+1  A: 

You could #define virtual Something_else which would give compiler errors when anyone used virtual, but they wouldn't make any sense without a bit more work.

Salgar
Win solution. `#define virtual void fail(){static_assert(false, "No virtual functions allowed!");}`
DeadMG
Counter: `#undef virtual`
Dashogun
+3  A: 

Boost.TypeTraits offers an is_polymorphic trait, but you might have to do some trickery to get it to apply everywhere it's needed. (For example, calling is_polymorphic on a base class won't tell you if a derived class introduced a virtual function.)

Depending on your build system and available tools, you may be able to introduce checks there. For example, if I run nm -C on an object file created by GCC, I see the following output for a simple test class with virtual functions:

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

So I could set up my makefile (or whatever) to run nm -C on all object files and raise an error if any contain vtable for.

Josh Kelley
+4  A: 

On commit to your repository,
For each class shared in this manner,
if the word virtual appears in the file
fail the commit, send an email to a senior developer, and dock the pay of the offending party.

Bill
+4  A: 

GCC (and may be others) gives a warning when a virtual function shows up in a class with non-virtual destructor.

Give all your shared classes an explicit non-virtual destructor (doing nothing?), and treat warnings as errors.

Arkadiy
Although this wouldn't stop a newbie developer from adding his own virtual destructor...
Josh Kelley
A newbie could change base class destructor to virtual - you need a !COMMENTARY! there. He/she could not add a virtual destructor to a derived class witout triggering the same warning.
Arkadiy
I did a quick test, and it looks like adding a virtual destructor to a derived class does not trigger a warning, at least for GCC 4.3.2. That would be an odd practice, though, so you're right, a !COMMENTARY! should stop most misuses.
Josh Kelley
In a deep inheritance hierarchy requiring the same boilerplate !COMMENTARY! in every derived class would get tedious. Doing so would simply underscore the inability of C++ to allow one to factor out this important property.
John Yates
+2  A: 

You can use is_polymorphic is combination with BOOST_STATIC_ASSERT to create a compiler error when someone adds a virtual function to a class. Put the BOOST_STATIC_ASSERT call in the implementation file for your class.

#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 );
}
John Dibling