Reputation: 73245
Let's suppose I have a shared library named libplugin
. In this shared library, there is a class:
class Plugin
{
public:
virtual void doStuff();
};
Let's also suppose that there is another shared library named libspecialplugin
. It contains the following class and function:
class SpecialPlugin : public Plugin
{
public:
virtual void doStuff();
};
Plugin *createSpecialPlugin()
{
return new SpecialPlugin;
}
Now, suppose I change Plugin
and add the following method:
virtual void doMoreStuff();
I do not recompile libspecialplugin
.
What happens when I do this:
Plugin *plugin = createSpecialPlugin();
plugin->doMoreStuff();
I'm guessing one of the following happens:
Plugin::doMoreStuff()
method is invokedDoes the libspecialplugin
library contain information that libplugin
can use to determine which of its methods are overridden - even at runtime? I'm a little fuzzy on what exactly is supposed to happen here.
Upvotes: 5
Views: 1651
Reputation: 54345
I have to add the giant disclaimer that "Everything to do with vtables is implementation defined."
This will work fine provided that the Plugin constructor and destructor are not declared inline in the header. It has to be an actual function call to the Plugin constructor in the libplugin.so library. This means the header has to declare the constructor and destructor but not define them in order to avoid generating the compiler's automatic versions.
It would look like:
class Plugin
{
public:
Plugin();
~Plugin();
virtual void doStuff();
};
Also provided that the new virtual function is added at the end of the class. If it causes any of the other functions in the vtable to move, that will ruin the ABI.
Then when the Plugin base class is constructed it will create the new vtable with the extra function. Then SpecialPlugin will adjust its one virtual function and complete the construction.
Some of this may depend on particular compiler implementations of vtbl pointers, but I have seen it done.
Upvotes: 1
Reputation: 30597
You are effectively violating the "One Definition Rule" by having the same class (Plugin
) defined differently in two different translation units within any program that uses the two libraries.
The standard says (C++11 ISO 14882:2011, §3.2 para 5):
There can be more than one definition of a class type (Clause 9) ... in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then:
- each definition of D shall consist of the same sequence of tokens; and
...
Your class Plugin
has two different definitions, one baked into libplugin and the other in libspecialplugin, so it does not comply with the standard.
The outcome of this is not defined by the standard, so anything could happen.
Upvotes: 8