problem regarding inheritance

F

frank_skare

Hello everybody,
I'm writing a COM component and don't want to put the IUnknown
implementation in every COM class so I'm using inheritance. I'm
getting a error 'cannot instantiate abstract class' even though all
virtual methods are implemented. Can anybody tell me what I'm doing
wrong?

thanks
Frank


#include "stdafx.h"
#include <shlobj.h>

class ComBase
{
public:
STDMETHOD(QueryInterface)(REFIID,LPVOID*);

STDMETHODIMP_(ULONG) AddRef()
{
return 0;
}

STDMETHODIMP_(ULONG) Release()
{
return 0;
}
};

class ComClass: public ComBase, public IShellExtInit
{
public:
STDMETHOD(QueryInterface)(REFIID,LPVOID*);
STDMETHOD(Initialize)(LPCITEMIDLIST, LPDATAOBJECT, HKEY);
};

STDMETHODIMP ComClass::QueryInterface(REFIID riid, LPVOID *ppv)
{
return E_NOTIMPL;
}

STDMETHODIMP ComClass::Initialize(
LPCITEMIDLIST pidlFolder,
LPDATAOBJECT pDataObj,
HKEY hProgID
)
{
return E_NOTIMPL;
}

int _tmain(int argc, _TCHAR* argv[])
{
ComClass argh;
return 0;
}
 
A

Alf P. Steinbach

* (e-mail address removed):
Hello everybody,
I'm writing a COM component and don't want to put the IUnknown
implementation in every COM class so I'm using inheritance. I'm
getting a error 'cannot instantiate abstract class' even though all
virtual methods are implemented. Can anybody tell me what I'm doing
wrong?


Regarding the code below, it would be much better if you made an attempt
at presenting your problem in standard C++.

#include "stdafx.h"
#include <shlobj.h>

The headers above are not standard C++ headers.

class ComBase
{
public:
STDMETHOD(QueryInterface)(REFIID,LPVOID*);

STDMETHODIMP_(ULONG) AddRef()
{
return 0;
}

STDMETHODIMP_(ULONG) Release()
{
return 0;
}
};

These macros are not standard C++.


class ComClass: public ComBase, public IShellExtInit
{
public:
STDMETHOD(QueryInterface)(REFIID,LPVOID*);
STDMETHOD(Initialize)(LPCITEMIDLIST, LPDATAOBJECT, HKEY);
};

STDMETHODIMP ComClass::QueryInterface(REFIID riid, LPVOID *ppv)
{
return E_NOTIMPL;
}

STDMETHODIMP ComClass::Initialize(
LPCITEMIDLIST pidlFolder,
LPDATAOBJECT pDataObj,
HKEY hProgID
)
{
return E_NOTIMPL;
}

int _tmain(int argc, _TCHAR* argv[])

In standard C++ you need (minimum)

int main()


{
ComClass argh;
return 0;
}


Rephrasing your problem in standard C++, you have code that is analogous to

struct IUnknown
{
virtual void unkFuncA() = 0;
virtual void unkFuncB() = 0;
virtual void unkFuncC() = 0;
};

struct IShellExtInit: IUnknown
{
virtual void seiFunc() = 0;
};

struct ComBase
{
virtual void unkFuncA() = 0;
void unkFuncB() {}
void unkFuncC() {}
};

struct ComClass: ComBase, IShellExtInit
{
void unkFuncA() {}
void seiFunc() {}
};

int main()
{
ComClass o; // Oops, doesn't compile.
}

ComClass inherits from ComBase and implements the single pure virtual
ComBase function unkFunkA. That's technically OK, although it doesn't
achieve the purpose of implementing IUnknown.

ComClass also inherits from IShellExtInit. I ShellExtInit has four pure
virtual functions, one it declares itself and three inherited from
IUnknown. ComClass implements two of them, seiFunc() and unkFuncA().

That leaves two pure virtual functions in ComClass, which means ComClass
is non-instantiable, an abstract class.

There are many ways to approach the problem of providing a stock
IUnknown implementation.

From a pure C++ point of view the most elegant and simple is to use
virtual inheritance to inherit in an implementation. However, that is
almost impossible to retrofit, since in your case ISHellExtInit is given
and presumably does not inherit virtually from IUnknown. An alternative
is then to use a templated bottom-level class, like

struct IUnknown
{
virtual void unkFuncA() = 0;
virtual void unkFuncB() = 0;
virtual void unkFuncC() = 0;
};

struct IShellExtInit: IUnknown
{
virtual void seiFunc() = 0;
};

template< class Base >
struct UnknownImpl: Base
{
void unkFuncA() {}
void unkFuncB() {}
void unkFuncC() {}
};

struct AbstractComClass: IShellExtInit
{
void seiFunc() {}
};

typedef UnknownImpl<AbstractComClass> ComClass;

int main()
{
ComClass o; // OK.
}

This is the technique used in the ATL and WTL libraries.


Cheers, & hth.,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top