【问题标题】:Multi-site execution : Getting rid of virtual table with inheritance (legacy code)多站点执行:通过继承摆脱虚拟表(遗留代码)
【发布时间】:2011-11-12 20:24:17
【问题描述】:

我在这个问题上被困了一段时间,我需要你的帮助。

我的 C++ 应用程序正在多个执行站点上运行。我的问题是我不能传递持有虚拟表的对象,因为站点不共享内存(因此来自给定对象的虚拟方法将导致未定义的行为)。 “我不能通过”我的意思是:我不想要任何虚拟桌子。

有趣的是不仅有继承,还有模板和怪诞的概念......

这里是代码

// "Main" code
List< Animals, 5 > list;
List< Animals, 8 > list2;
list.concatenate( list2 );

// GenericList.hpp
template< Type >
class GenericList 
{
 virtual getBuffer(void) = 0;
 virtual getSize(void) = 0;
 void concatenate( GenericList<Type> gList)
 {
  int size = gList.getSize(); // Call to the child...
  ...getBuffer()...
  // processing, etc.
 }
}

// List.hpp
template< Type, Size_ >
class List : public GenericList< Type >
{
 int getSize()
  {
   return Size_;
  }
 Type * getBuffer()
  {
   return buffer;
  }
 Type buffer[Size_];
}

我怎样才能摆脱继承?

编辑/根据前几个答案,我可以告诉你我不能实现更好的序列化,代码是私有的。

【问题讨论】:

  • 你到底在序列化什么?如果您在另一侧创建对象并使用相同的值填充其成员,则虚拟表在新站点上也应该有效。
  • 使用 CRTP 摆脱虚函数怎么样?
  • @RedX :这不完全是序列化,而是多频率(每个频率一个站点)。所以基本上,对象的一侧或另一侧是相同的。锐齿:我会调查的,谢谢。为什么没有发布作为答案? ;)
  • 数据是如何序列化的?您的序列化方案是否只是对char* 进行强制转换,然后以sizeof 作为字节数通过网络发送它?了解更多有关数据发送方式的信息可以让我们为您提供更好的建议。
  • 就是这样完成的;匿名缓冲区...

标签: c++ arrays pointers inheritance virtual


【解决方案1】:

我认为你把问题归咎于错误的部分......如果你有一个分布式系统,你必须确保通过网络发送的序列化数据包含足够的信息来重建对象的状态在连接的另一端。

我相信您面临的问题是您通过网络发送原始数据,而您应该有一个序列化机制,能够编码正在发送的对象的实际类型并在另一端重建对象与完全相同的类型。对于属于具有虚函数的类的对象,这将意味着两个对象不相等按位,因为在连接的每一端,指向 vtable 的指针将引用不同的内存中的位置,但它们将在语义上相等,这是您能够处理另一端的对象所需要的。

【讨论】:

  • 你说的很对,我也同意你的观点,但是(总有一个但是)我不能修改序列化机制……所以我只需要找到一个解决方法
【解决方案2】:

如果您只想摆脱虚拟表,您不必摆脱继承。你必须摆脱虚函数。查看您发布的代码,也许您可​​以进行一些更改,以便 getSizegetBufferGenericList 中,因此您可以将它们设为非虚拟,但这实际上取决于您的代码的其余部分。

然而,第一个问题是,为什么您首先要担心虚拟表?当你序列化对象时,你应该序列化它们的数据以保持它们的状态,而状态是你唯一应该传递的东西。

【讨论】:

  • 感谢您的帮助。我无法移动两者中的任何一个,因为“Size_”仅在孩子中定义。正如 cmets 中所说,它不完全是序列化,而是多频。很遗憾,但我无法更改对象在频率之间传递的方式(它是一个 java/C 中间件)。
  • @Isaac,那个频率到底是什么?...对象是通过引用传递的吗?您可以访问分配在堆上的数据,但不能访问 vtables 吗?至于使函数成为非虚拟函数——也许你可以有一个size 成员变量,它将在构造函数上设置,它的值将被返回而不是Size_。这样你可以在GenericList中保留一个非虚拟的getSize(),并且在使用List时仍然返回Size_的值。
  • 不,对象作为匿名缓冲区传递。我要试试你的方法,谢谢;)
  • @Isaac,如果您最终卡在 vtable 上,另一个(有点难看的)选项是在反序列化后恢复正确的 vtable 指针。相同类型的对象指向同一个 vtable,因此如果您在目标上创建 List 的虚拟实例,则可以将其 vtable 指针分配给您从网络中获得的任何 List 对象。假设对象的内存布局在两端是相同的(没有不同的对齐方式),它应该“恢复”你收到的对象。
  • 我终于设法解决了我的问题:我复制了母类中的属性,并在子构造函数中对其进行了初始化...感谢您的帮助!
猜你喜欢
  • 2013-07-24
  • 2011-03-09
  • 2011-09-03
  • 2017-03-31
  • 1970-01-01
  • 2015-11-21
  • 1970-01-01
  • 1970-01-01
  • 2014-10-12
相关资源
最近更新 更多