COM服务器实例作为类成员 [英] COM Server Instance as Class Member

查看:63
本文介绍了COM服务器实例作为类成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在具有多个接口的COM服务器中,是否可以将任何接口的任何共同类的实例创建为某个类的成员?如果尝试这样做,则会出现编译器错误"C2259:由于以下成员而无法实例化抽象类:QueryInterface,AddRef ....".

In COM server with multiple interfaces, can instance of any of co-class of any of the interfaces be created as member of some class? If I try to do so, I get compiler error "C2259 : cannot instantiate abstract class due to following members : QueryInterface, AddRef ....". How this can be resolved?

推荐答案

如果采用这种方式,则必须实例化最终类中的vtable(源自基类的iPersistStream)示例:
If you do it in this way you have to instanciate the vtables in the final class (iPersistStream derived from base classes) example:
class iPersist : public IPersist
{
public: // IUnknown
	virtual HRESULT	__stdcall	QueryInterface(REFIID riid,void** ppv){ return E_NOINTERFACE; }
	virtual ULONG __stdcall		AddRef(){ return InterlockedIncrement(&_ref); }
	virtual ULONG __stdcall		Release(){ if(InterlockedDecrement(&_ref)) return _ref; delete this; return 0; }

public: //	IPersist
	virtual HRESULT __stdcall GetClassID(CLSID *pClassID){ if(!pClassID) return E_POINTER; memcpy(pClassID,&IID_NULL,sizeof(CLSID)); return S_OK; }

	iPersist(){ _ref=1; }
protected:
	virtual ~iPersist(){}
	long	_ref;
};

class iStream : public IStream
{
public: // IUnknown
	virtual HRESULT	__stdcall	QueryInterface(REFIID riid,void** ppv){ return E_NOINTERFACE; }
	virtual ULONG __stdcall		AddRef(){ return InterlockedIncrement(&_ref); }
	virtual ULONG __stdcall		Release(){ if(InterlockedDecrement(&_ref)) return _ref; delete this; return 0; }


public: // ISequentialStream
	virtual	HRESULT __stdcall Read(void *pv,ULONG cb,ULONG *pcbRead){ return E_NOTIMPL; }
	virtual	HRESULT __stdcall Write(const void *pv,ULONG cb,ULONG *pcbWritten){ return E_NOTIMPL; }

public: // IStream
	virtual	HRESULT __stdcall Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition){ return E_NOTIMPL; }
	virtual HRESULT __stdcall SetSize(ULARGE_INTEGER libNewSize){ return E_NOTIMPL; }
	virtual	HRESULT __stdcall CopyTo(IStream* pstm,ULARGE_INTEGER cb,ULARGE_INTEGER *pcbRead,ULARGE_INTEGER *pcbWritten){ return E_NOTIMPL; }
	virtual HRESULT __stdcall Commit(DWORD grfCommitFlags){ return E_NOTIMPL; }
	virtual HRESULT __stdcall Revert(){ return E_NOTIMPL; }
	virtual HRESULT __stdcall LockRegion(ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType){ return E_NOTIMPL; }
	virtual HRESULT __stdcall UnlockRegion(ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType){ return E_NOTIMPL; }
	virtual HRESULT __stdcall Stat(STATSTG* pstatstg,DWORD grfStatFlag){ return E_NOTIMPL; }
	virtual HRESULT __stdcall Clone(IStream** ppstm){ return E_NOTIMPL; }

	HRESULT	Open(const TCHAR* file,int mode){ /* open the file*/ return _hf?S_OK:E_FAIL; }
	HRESULT	Close(){ if(_hf) CloseHandle(_hf); _hf=0; }
	
	iStream(){ _ref=1; _hf=0; }
protected:
	virtual ~iStream(){ Close(); }
	long		_ref;
	HANDLE	_hf;
};

class iPersistStream : public iPersist, public iStream
{
public: // IUnknown
	virtual HRESULT	__stdcall	QueryInterface(REFIID riid,void** ppv)
	{
		if(IID_IUnknown         ==riid) return *(IUnknown         **)ppv=(iPersist*)this,AddRef(),S_OK;
		if(IID_IPersist         ==riid) return *(IPersist         **)ppv=this,AddRef(),S_OK;
		if(IID_IStream          ==riid) return *(IStream          **)ppv=this,AddRef(),S_OK;
		if(IID_ISequentialStream==riid) return *(ISequentialStream**)ppv=this,AddRef(),S_OK;
		return E_NOINTERFACE;
	}
	virtual ULONG __stdcall		AddRef()	{ return iPersist::AddRef(); }
	virtual ULONG __stdcall		Release()	{ return iPersist::Release(); }

	iPersistStream(){}
protected:
	virtual ~iPersistStream(){}
};



否则,您可以通过这种方式进行操作(实例化一次,iPersistStream2从接口派生),例如:



otherwise you can do it in this way (instanciate once, iPersistStream2 derived from interfaces), example:

class iPersistStream2 : public IPersist, public IStream
{
public: // IUnknown
	virtual HRESULT	__stdcall	QueryInterface(REFIID riid,void** ppv)
	{
		if(IID_IUnknown         ==riid) return *(IUnknown         **)ppv=(IPersist*)this,AddRef(),S_OK;
		if(IID_IPersist         ==riid) return *(IPersist         **)ppv=this,AddRef(),S_OK;
		if(IID_IStream          ==riid) return *(IStream          **)ppv=this,AddRef(),S_OK;
		if(IID_ISequentialStream==riid) return *(ISequentialStream**)ppv=this,AddRef(),S_OK;
		return E_NOINTERFACE;
	}
	virtual ULONG __stdcall		AddRef(){ return InterlockedIncrement(&_ref); }
	virtual ULONG __stdcall		Release(){ if(InterlockedDecrement(&_ref)) return _ref; delete this; return 0; }

public: //	IPersist
	virtual HRESULT __stdcall GetClassID(CLSID *pClassID){ if(!pClassID) return E_POINTER; memcpy(pClassID,&IID_NULL,sizeof(CLSID)); return S_OK; }

public: // ISequentialStream
	virtual	HRESULT __stdcall Read(void *pv,ULONG cb,ULONG *pcbRead){ return E_NOTIMPL; }
	virtual	HRESULT __stdcall Write(const void *pv,ULONG cb,ULONG *pcbWritten){ return E_NOTIMPL; }

public: // IStream
	virtual	HRESULT __stdcall Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition){ return E_NOTIMPL; }
	virtual HRESULT __stdcall SetSize(ULARGE_INTEGER libNewSize){ return E_NOTIMPL; }
	virtual	HRESULT __stdcall CopyTo(IStream* pstm,ULARGE_INTEGER cb,ULARGE_INTEGER *pcbRead,ULARGE_INTEGER *pcbWritten){ return E_NOTIMPL; }
	virtual HRESULT __stdcall Commit(DWORD grfCommitFlags){ return E_NOTIMPL; }
	virtual HRESULT __stdcall Revert(){ return E_NOTIMPL; }
	virtual HRESULT __stdcall LockRegion(ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType){ return E_NOTIMPL; }
	virtual HRESULT __stdcall UnlockRegion(ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType){ return E_NOTIMPL; }
	virtual HRESULT __stdcall Stat(STATSTG* pstatstg,DWORD grfStatFlag){ return E_NOTIMPL; }
	virtual HRESULT __stdcall Clone(IStream** ppstm){ return E_NOTIMPL; }

	HRESULT	Open(const TCHAR* file,int mode){ /* open the file*/ return _hf?S_OK:E_FAIL; }
	HRESULT	Close(){ if(_hf) CloseHandle(_hf); _hf=0; }

	iPersistStream2(){ _ref=1; _hf=0; }
protected:
	virtual ~iPersistStream2(){}
	long		_ref;
	HANDLE	_hf;
};


您无法实例化抽象类.您应该了解哪些类是抽象的:那些类至少具有一个纯虚方法,通常也被称为抽象(在较新的语言中,通常在一种或两种情况下都使用语言关键字abstract). >
那么,您如何想象抽象类的实例?如果允许,则将尝试从该方法的地址为null的VMT调用抽象方法,这将导致异常.因此,应该重写所有抽象方法以使该类成为非抽象类并允许实例化.您提到的方法在每个COM类的基类中(因为它需要实现IUnknown).

大多数用于C ++的COM库可帮助自动实现COM接口方法,但您也可以自行完成.用C ++语法连接的COM只是抽象类,其中所有成员都是纯虚函数.

—SA
You cannot instantiate an abstract class. You should understand which classes are abstract: those having at least one pure virtual method, which is often called abstract as well (in newer language it is typical to have the language key word abstract in one or both cases).

So, how would you imagine the instance of the abstract class? If it was allowed, the abstract method would be attempted to to call from the VMT where the address of the method is null, which would cause the exception. So, all abstract methods should be overridden to make that class non-abstract and allow instantiation. The method you mentioned are in the base class of every single COM class (because it needs to implement IUnknown).

Most COM libraries for C++ help to implement COM interface methods automatically, but you cal also do it your self. COM interfaced in C++ syntax are merely abstract classed where all members are pure virtual functions.

—SA


您可以将接口存储为指针.
:)
You may store the interfaces as pointers.
:)


这篇关于COM服务器实例作为类成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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