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:
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:
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:
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:
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:
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){ 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:
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(){}
};
otherwise you can do it in this way (instanciate once, iPersistStream2 derived from interfaces), example:
class iPersistStream2 : public IPersist, public IStream
{
public:
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:
virtual HRESULT __stdcall GetClassID(CLSID *pClassID){ if(!pClassID) return E_POINTER; memcpy(pClassID,&IID_NULL,sizeof(CLSID)); return S_OK; }
public:
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:
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){ 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;
};