Shared memory originally only allows POD structures (at heart, they may have constructors/copy/etc...).
Boost.Interprocess
raises the bar by emulating pointers semantics on top of offsets into the shared memory segment.
However, a virtual pointer is not a pointer to pure data, it's a pointer to code sections, and that is where things get complicated because code sections are not necessarily mapped to the same address from one process to another (even if they were launched from the same binary).
So... no, virtual pointers-polymorphic objects cannot be stored in shared memory.
However, just because many C++ implementations chose to use a virtual-pointer mechanism does not mean that this is the only way to have polymorphic behavior. For example, in LLVM and Clang they build on their closed hierarchies to get polymorphism without virtual pointers (and RTTI) so as to lower memory requirements. Those objects could, effectively, be stored in shared memory.
So, how to get polymorphism compatible with shared memory: we need not to store pointers to tables/functions, however we can store indexes.
Example of the idea, but could probably be refined.
/// In header
#include <cassert>
#include <vector>
template <class, size_t> class BaseT;
class Base {
template <class, size_t> friend class BaseT;
public:
int get() const; // -> Implement: 'int getImpl() const' in Derived
void set(int i); // = 0 -> Implement: 'void setImpl(int i)' in Derived
private:
struct VTable {
typedef int (*Getter)(void const*);
typedef void (*Setter)(void*, int);
VTable(): _get(0), _set(0) {}
Getter _get;
Setter _set;
};
static std::vector<VTable>& VT(); // defined in .cpp
explicit Base(size_t v): _v(v) {}
size_t _v;
}; // class Base
template <class Derived, size_t Index>
class BaseT: public Base {
public:
BaseT(): Base(Index) {
static bool const _ = Register();
(void)_;
}
// Provide default implementation of getImpl
int getImpl() const { return 0; }
// No default implementation setImpl
private:
static int Get(void const* b) {
Derived const* d = static_cast<Derived const*>(b);
return d->getImpl();
}
static void Set(void* b, int i) {
Derived* d = static_cast<Derived*>(b);
d->setImpl(i);
}
static bool Register() {
typedef Base::VTable VTable;
std::vector<VTable>& vt = Base::VT();
if (vt.size() <= Index) {
vt.insert(vt.end(), Index - vt.size() + 1, VTable());
} else {
assert(vt[Index]._get == 0 && "Already registered VTable!");
}
vt[Index]._get = &Get;
vt[Index]._set = &Set;
}
}; // class BaseT
/// In source
std::vector<VTable>& Base::VT() {
static std::vector<VTable> V;
return V;
} // Base::VT
int Base::get() const {
return VT()[_v]._get(this);
} // Base::get
void Base::set(int i) {
return VT()[_v]._set(this, i);
} // Base::set
Okay... I guess that now you appreciate the compiler's magic...
Regarding the usage, it's fortunately much simpler:
/// Another header
#include <Base.h>
// 4 must be unique within the hierarchy
class Derived: public BaseT<Derived, 4> {
template <class, size_t> friend class BaseT;
public:
Derived(): _i(0) {}
private:
int getImpl() const { return _i; }
void setImpl(int i) { _i = i; }
int _i;
}; // class Derived
In action at ideone.