增加类的数据大小. [英] Increase in data size of a class.

查看:81
本文介绍了增加类的数据大小.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,
我只是在读一本关于COM的书.关于使用DLL的动态链接,据说如果我增加类的大小(即,如果我改变类的布局),这对于客户端是有问题的,客户端也需要重新编译dll.

即以前我的课就像

Hello ,
I am just reading one book on COM. About Dynamic Linking using DLL it is said that if I increase size of my class (i.e if I change layout of class) it is problematic for client and client need to recompile dlls as well.

i.e Previously my class is like,

class __declspec(dllexport) CMath {
 int someData;
};



现在就像,




and now it is like,


class __declspec(dllexport) CMath {
 int someData;
int someMoreData; //Why problematic? 

};




谢谢和问候.




Thanks and Regards.

推荐答案

这当然很糟糕,应该避免,但这不是很严重的问题.您的服务器将使用新版本的CMath,客户端将使用旧的CMath,而不使用someMoreData.其他所有内容都取决于您在客户端上使用此类以及在服务器上执行的操作.例如,客户端可能总是获得在服务器上构造的此类的实例.客户端将看不到多余的字段.

相反的情况会造成很大的麻烦,最好是内存访问冲突异常 .想象一下,您在客户端上创建了一个实例并将其传递给服务器.在这种情况下,实例不具有someMoreData.这两个类本质上是不同的类型.现在,如果服务器使用这样的实例并访问不存在的字段someMoreData,会发生什么?它将尝试访问此类实例后面的内存.正如我所说,访问冲突是最好的情况.更糟糕的是,服务器可能在实例之后访问内存并破坏其他对象的内存.我可以想象找到这样的错误会很困难...

—SA
It is bad of course and should be avoided but it is not extremely problematic. You server will work with new version of CMath and the client with the old CMath, without someMoreData. Everything else depends on what you do with this class on client and what on server. For example, it''s possible that a client always gets an instance of this class constructed on the server. The extra field will be invisible to a client, that''s it.

The opposite situation will cause big troubles, memory access violation exception at best. Imagine you create an instance on client and pass it to the server. In this case, an instance does not have someMoreData. The two classes are essentially different types. Now, what happens if a server works with such an instance and access non-existing field someMoreData? It will try to access memory behind the instance of this class. As I say, access violation is the best possible case. Worse, the server could access memory after the instance and damage memory of some other object. I can imagine how hard would be to find such a bug…

—SA


我认为您误解了增大尺寸的含义. COM对象仅由vtable中的一组功能组成. vtable与cpp类中的虚拟函数非常相似.在COM中,没有像cpp中那样的对象强制转换.对象强制转换始终是QueryInterface.如果您的界面长大(即一些其他功能),则必须在QueryInterface中使用新的转换(IID_MyNewClassVersion1-> IID_MyNewClassVersion2).为了使发布的界面保持一致,您可以公开一个包含其他功能的新界面.这就是为什么使用界面(可以是另一个应用程序)的客户端依赖界面布局的原因. 也许想象您有一个带有3个函数的接口(IUnknown函数也是如此),让他们调用:
I think you misunderstood the meaning of increasing the size. COM objects only consists of a set of function in a vtable. The vtable is very similar to virtual function in a cpp-class. In COM there is no object cast like in cpp. The object cast is always QueryInterface. If your interface grows up (i.e. some additional function) you MUST use a new cast (IID_MyNewClassVersion1 -> IID_MyNewClassVersion2) inside QueryInterface. To keep published interfaces consistent you can expose a new interface including the additional functions. Thats why the client that uses the interface (this can be another application) relies on the interface layout.
Perhaps imagine you have a interface with 3 functions (the IUnknown functions too) let them call:
<br />
virtual HRESULT __stdcall a() = 0;<br />
virtual HRESULT __stdcall b() = 0;<br />
virtual HRESULT __stdcall c() = 0;<br />


一个较旧的应用程序依赖于该界面布局.有时,以后您想增加功能时,可以将布局更改为:


an older application relies on that interface layout. Sometimes later you want to increase functionality you change the layout to:

<br />
virtual HRESULT __stdcall a() = 0;<br />
virtual HRESULT __stdcall b1() = 0;<br />
virtual HRESULT __stdcall b() = 0;<br />
virtual HRESULT __stdcall c() = 0;<br />


在这种情况下,较旧的应用程序将调用您稍后实现的函数(即,调用函数b()将改为调用函数b1()).
否则,如果更新使用该接口的客户端,则可能是使用不存在的函数调用较旧的接口提供程序(即,您调用c()的实现将在较旧的接口中不存在).
因此,您可以公开一个新的界面,例如:
//接口1具有guid == IID_MyNewClassVersion1
//包含函数


in this case the older application will call a function that youve implememnted later (i.e. call function b() will instead call the function b1()).
Otherwise if you update the client that uses that interface it might be older interface provider will been called with a non existing function (i.e. you call c() the implementation will not exist in the older interface).
So you can expose a new interface lets say:
// interface 1 has the guid==IID_MyNewClassVersion1
// contains the functions

<br />
virtual HRESULT __stdcall a() = 0;<br />
virtual HRESULT __stdcall b() = 0;<br />
virtual HRESULT __stdcall c() = 0;<br />


//接口2具有guid == IID_MyNewClassVersion2
//包含函数


// interface 2 has the guid==IID_MyNewClassVersion2
// contains the functions

<br />
virtual HRESULT __stdcall a() = 0;<br />
virtual HRESULT __stdcall b1() = 0;<br />
virtual HRESULT __stdcall b() = 0;<br />
virtual HRESULT __stdcall c() = 0;<br />


函数查询界面在不同的界面之间有区别:


the function query interface distinquish between the different interfaces:

<br />
HRESULT QueryInterface(RIID riid,void** ppv)<br />
{<br />
  if(IID_MyNewClassVersion1) return *(MyNewClassVersion1**)ppv=this,AddRef(),S_OK;<br />
  if(IID_MyNewClassVersion2) return *(MyNewClassVersion2**)ppv=this,AddRef(),S_OK;<br />
  return E_NOINTERFACE;<br />
}<br />


问候.


这篇关于增加类的数据大小.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆