problem regarding inheritance

Discussion in 'C++' started by frank_skare@yahoo.de, Feb 10, 2008.

  1. Guest

    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;
    }
     
    , Feb 10, 2008
    #1
    1. Advertising

  2. * :
    > 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

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Feb 10, 2008
    #2
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. darkstorm
    Replies:
    3
    Views:
    352
    Malte Starostik
    Mar 29, 2005
  2. He Shiming
    Replies:
    2
    Views:
    347
    Janusz Szpilewski
    Jun 10, 2005
  3. Anarki
    Replies:
    5
    Views:
    469
    James Kanze
    Jul 7, 2007
  4. Angus
    Replies:
    3
    Views:
    340
    H. S. Lahman
    Jan 4, 2009
  5. Amit Jain
    Replies:
    7
    Views:
    486
    Roedy Green
    Nov 28, 2009
Loading...

Share This Page