Does a pure abstract C++ class declared in a header used in different projects (without compile time linking) share the same Virtual Table model?

StackOverflow https://stackoverflow.com/questions/9183616

Question

I have a C++ header declaring a class composed of pure virtual methods only. I have two DLLs using that header, (with one implementing that interface) but not linked at compile time. One DLL is loading the other one dynamically, passing a pointer of the implemented interface to the other. Are these DLL's sharing the same virtual table structure?

Was it helpful?

Solution

You're safe.

The order in which the methods appear in the vftable is determined by the base class structure, and that's all you should care about. But this is compiler specific, so use the same compiler for generating the dll's. Don't rely on them being backward-compatible (or at least check the documentation).

Assume you have the following header:

//header.h

class A
{
public:
    virtual void foo() = 0;
    virtual void goo() = 0;
};

And you have B.dll with the following class:

class B : public A
{
public:
    virtual void foo() {}
    virtual void goo() {}
}

Now, in X.dll, you receive a pointer to an A that is a B object created in B.dll.

The call

void test( A* a )
{ 
   a->foo();
}

will invoke B::foo().

One neat experiment you can try is to compile B.dll with header.h and when you compile X.dll, invert the order of the methods in header.h:

//header.h

class A
{
public:
    virtual void goo() = 0;
    virtual void foo() = 0;
};

In this case, although you should never do this, the same call to test() in X.dll will probably call the method B::goo(). That is because X.dll assumes the vftable present in the header. It's undefined behavior though; I just wrote this example to make a point.

OTHER TIPS

Of course, the class header is enough to build the complete class (speaking about the in-memory layout here, how everything is positioned, not the actual data inside it), including the precise virtual table structure.

Think about it, each linking object (your .cpp files) are compiled separately, with only the header files in common, but at compile time the compiler has to know the precise structure of the virtual table to route virtual calls correctly.

Doozy of a question to read through by the way...

If I understand correctly, you've got something like this:

A.h

class A
{
public:
    virtual void foo()=0;
}

B.cpp

#include <A.h>

class B : public A
{
public:
    void foo()
    {}
}

C.cpp

#include <A.h>

void bar(A * a)
{}

So B.cpp has a class implementing A, and C.cpp has some function accepting a pointer to an instance of A (which you provide with an instance of B). Is that correct?

If so, then yes, these share a vtable. The vtable is created by compiling class B, and C.cpp doesn't have any vtables of its own at all.

This is all compiler dependent, but in general, when a class is pure virtual and none of the member functions is defined in a translation unit, the compiler will generate the vtable as a weak symbol. In your particular case, the different translation units will generate separate exactly equal vtables for the base type and the linker/loader will discard all but one of the symbols as it would with any other weak symbol (think of a templated non-inlined function).

Note however that the generation of the vtable is not standardized which means that if you mix code from two different compilers or even versions you can cause an ODR violation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top