C++ 是否可以在共享内存中存储多态类?
假设我有类C++ 是否可以在共享内存中存储多态类?,c++,boost,shared-memory,boost-interprocess,C++,Boost,Shared Memory,Boost Interprocess,假设我有类Base和派生:public Base。 我使用boost::进程间库构建了一个共享内存段。是否可能有类似的代码: Base* b = new Derived(); write(b); //one app writes Base* b2 = read(b); //second app reads //b equals b2 (bitwise, not the ptr location) 我在这里看到的问题是,例如,基类的派生类所需的空间未知(那么要分配多少shmem?) Q:如何在
Base
和派生:public Base
。
我使用boost::进程间库构建了一个共享内存段。是否可能有类似的代码:
Base* b = new Derived();
write(b); //one app writes
Base* b2 = read(b); //second app reads
//b equals b2 (bitwise, not the ptr location)
我在这里看到的问题是,例如,基类的派生类所需的空间未知(那么要分配多少shmem?)
Q:如何在应用程序之间通过指针传递对象?只需阅读
特别是:
虚拟禁止
虚拟表指针和虚拟表位于地址中
构建对象的过程的空间,因此如果我们放置
使用虚拟函数或虚拟基类初始化,虚拟
放置在共享内存中的指针对于其他进程无效
他们会崩溃的
这个问题很难解决,因为每个过程都需要一个
不同的虚拟表指针和包含该指针的对象
指针在许多进程中共享。即使我们把地图
在每个进程的同一地址区域中,虚拟表可以
在每个进程中都使用不同的地址。启用虚拟功能
对于进程之间共享的对象,需要对编译器进行深入的更改
虚拟函数的性能会受到影响。这就是为什么
Interprocess没有任何支持虚拟功能的计划
以及进程之间共享的映射区域中的虚拟继承
我相信您正在研究对象的序列化。看看 您可以采用以下几种方法: 1.序列化C++类 2.将数据发送到其他应用程序
3.在C++内存类中,
共享内存原本只允许POD结构(在本质上,它们可能有构造函数/拷贝/……)
Boost.Interprocess
通过在共享内存段的偏移量之上模拟指针语义来提高标准
然而,虚拟指针不是指向纯数据的指针,而是指向代码段的指针,这就是事情变得复杂的原因,因为代码段不一定从一个进程映射到另一个进程的同一地址(即使它们是从同一二进制启动的)
所以。。。不,虚拟指针多态对象不能存储在共享内存中
然而,正因为许多C++实现选择使用虚拟指针机制,并不意味着这是唯一的具有多态行为的方式。例如,在LLVM和Clang中,它们构建在封闭的层次结构上,以获得无虚拟指针(和RTTI)的多态性,从而降低内存需求。这些对象可以有效地存储在共享内存中 因此,如何使多态性与共享内存兼容:我们不需要存储指向表/函数的指针,但可以存储索引 这是一个很好的例子,但可能需要改进
/// 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
///在标题中
#包括
#包括
模板类BaseT;
阶级基础{
模板好友类BaseT;
公众:
int get()const;//->在派生表达式中实现:“int getImpl()const”
void set(int i);//=0->在派生的
私人:
结构VTable{
typedef int(*Getter)(void const*);
typedef void(*Setter)(void*,int);
VTable():_get(0),_set(0){}
获得;
Setter_集;
};
静态std::vector&VT();//在.cpp中定义
显式基(size_t v):_v(v){}
尺寸(t)v ;;
}; // 阶级基础
模板
BaseT类:公共基{
公众:
BaseT():基(索引){
静态布尔常数=寄存器();
(无效)—;
}
//提供getImpl的默认实现
int getImpl()常量{return 0;}
//没有默认的实现setImpl
私人:
静态int Get(无效常量*b){
导出常数*d=静态_转换(b);
返回d->getImpl();
}
静态无效集(无效*b,整数i){
导出*d=静态_转换(b);
d->setImpl(i);
}
静态布尔寄存器(){
typedef Base::VTable VTable;
std::vector&vt=Base::vt();
如果(vt.size()//从上面的示例中,我已经删除了VTable
//我还根据boost::interprocess删除了静态变量
//静态变量不适用于共享内存,我也没有看到
//为所有派生类实际构建VTable有什么好处
#包括
#包括
#包括
模板类BaseT;
阶级基础{
模板好友类BaseT;
boost::函数\u get;
boost::函数\u集;
公众:
int get(){
return_get();
}//>在派生中实现:“int get()”
无效集(int i){
_第(i)组;
}//=0->在派生的
};//类基
模板
BaseT类:公共基{
公众:
BaseT():Base(),impl(static_cast(this)){
Base::_get=boost::bind(&BaseT::get,this);
Base::_set=boost::bind(&BaseT::set,this,_1);
}
int get(){
返回impl->get();
}
无效集(int i){
impl->set(i);
}
私人:
导出*impl;
};
//Base的一些实现
结构A:BaseT{
int get(){
return 101;//测试实现
}
无效集(int i){
;//实现在这里进行
}
};
//Base的一些B实现
结构B:BaseT{
int get(){
return 102;//测试实现
}
无效集(int i){
;//实现在这里进行
}
};
int main(){
BaseT objectA;
BaseT objectB;
基本*a=&objectA;
Base*b=&objectB;
std::cout get()//在重新定义时,我改变了getter中constance的语义,
//并将非常量派生指针用于getter和setter。
//但原始simantics可以保存如下:
int get()常量{
//返回impl->get();
//这强制get必须是常量
静态_cast(this)->get();
}
很好,exac
/// 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
//From the example above , I have removed VTable
// I also removed static variables as per boost::interprocess
// static variable don't work with shared memory, and also I did not see
// any advantage in actually builting a VTable for all derived classes
#include <vector>
#include <boost/bind.hpp>
#include <boost/function.hpp>
template <class> class BaseT;
class Base {
template <class> friend class BaseT;
boost::function< int (void) > _get;
boost::function< void (int) > _set;
public:
int get() {
return _get();
} // -> Implement: 'int get() ' in Derived
void set(int i) {
_set(i);
} // = 0 -> Implement: 'void set(int i)' in Derived
}; // class Base
template <class Derived>
class BaseT : public Base {
public:
BaseT() : Base(), impl(static_cast<Derived *> (this)) {
Base::_get = boost::bind(&BaseT<Derived>::get, this);
Base::_set = boost::bind(&BaseT<Derived>::set, this, _1);
}
int get() {
return impl->get();
}
void set(int i) {
impl->set(i);
}
private:
Derived * impl;
};
//some A implementation of Base
struct A : BaseT<A> {
int get() {
return 101; //testing implementation
}
void set(int i) {
; //implementation goes here
}
};
//some B implementation of Base
struct B : BaseT<B> {
int get() {
return 102; //testing implementation
}
void set(int i) {
; //implementation goes here
}
};
int main() {
BaseT<A> objectA;
BaseT<B> objectB;
Base *a = &objectA;
Base *b = &objectB;
std::cout << a->get() << " returned from A class , "
<< b->get() << " returned from B class " << std::endl;
return 0;
}
//While redefining I changed semantics of constnance in getter,
//and had non- const Derived pointer used for both getter and setter.
//But original simantics can be preserved as following:
int get() const {
//return impl->get();
//this enforces that get has to be const
static_cast<const Derived *> (this)->get() ;
}