none
How to set up a simple base class for two ATL/COM classes RRS feed

  • Question

  • I've created two property handler classes using ATL (and the ATL wizard).  Both classes implement the IPropertyStore interface, and they share some functionality.  For example, they both have the same IPropertyStore::Commit() method.  So I thought I'd set up a simple base class for them to derive from.  So I've created a base class just as a simple C++ class -- not with the ATL wizard (I don't want the base class to be instantiated or set up for registration, etc.).  But it's in the same folder as the two ATL classes.  And I've also added the proper inheritance to the ATL class declarations.

    Here's the problem: if I declare and implement Commit() in my base class, and then I omit any Commit() declaration from the derived ATL classes, I get an ATL error about being unable to instantiate an abstract class.  I guess that's because the derived classes need to declare Commit() in order for them to properly implement IPropertyStore.  But then if I include Commit() declarations in the ATL classes (with implementation still in the base class), I get a linker error.

    So I'm wondering what the trick is for setting up a base class for two derived ATL classes.  Any guidance would be greatly appreciated.






    • Edited by amt528 Monday, October 21, 2019 1:41 PM
    Monday, October 21, 2019 1:36 PM

Answers

  • Assuming that IPropertyStore::Commit is the only method that you want to define in the C++ base class --

    class CPropBase
    {
    public:
    	CPropBase();
    	virtual ~CPropBase();
    	virtual HRESULT STDMETHODCALLTYPE GetCount(
    		/* [out] */ __RPC__out DWORD *cProps) = 0;
    
    	virtual HRESULT STDMETHODCALLTYPE GetAt(
    		/* [in] */ DWORD iProp,
    		/* [out] */ __RPC__out PROPERTYKEY *pkey) = 0;
    
    	virtual HRESULT STDMETHODCALLTYPE GetValue(
    		/* [in] */ __RPC__in REFPROPERTYKEY key,
    		/* [out] */ __RPC__out PROPVARIANT *pv) = 0;
    
    	virtual HRESULT STDMETHODCALLTYPE SetValue(
    		/* [in] */ __RPC__in REFPROPERTYKEY key,
    		/* [in] */ __RPC__in REFPROPVARIANT propvar) = 0;
    
    	virtual HRESULT STDMETHODCALLTYPE Commit(void);
    };
    

    Implement the Commit method in the ATL classes derived from CPropBase like this -

    HRESULT CPropObj1::Commit(void)
    {
    	return CPropBase::Commit();
    }
    Depending on how you have actually structured your classes and inheritance you could also derive CPropBase from IPropertyStore.


    • Edited by RLWA32 Monday, October 21, 2019 3:08 PM added comment
    • Marked as answer by amt528 Tuesday, October 22, 2019 2:47 PM
    Monday, October 21, 2019 2:49 PM

All replies

  • Assuming that IPropertyStore::Commit is the only method that you want to define in the C++ base class --

    class CPropBase
    {
    public:
    	CPropBase();
    	virtual ~CPropBase();
    	virtual HRESULT STDMETHODCALLTYPE GetCount(
    		/* [out] */ __RPC__out DWORD *cProps) = 0;
    
    	virtual HRESULT STDMETHODCALLTYPE GetAt(
    		/* [in] */ DWORD iProp,
    		/* [out] */ __RPC__out PROPERTYKEY *pkey) = 0;
    
    	virtual HRESULT STDMETHODCALLTYPE GetValue(
    		/* [in] */ __RPC__in REFPROPERTYKEY key,
    		/* [out] */ __RPC__out PROPVARIANT *pv) = 0;
    
    	virtual HRESULT STDMETHODCALLTYPE SetValue(
    		/* [in] */ __RPC__in REFPROPERTYKEY key,
    		/* [in] */ __RPC__in REFPROPVARIANT propvar) = 0;
    
    	virtual HRESULT STDMETHODCALLTYPE Commit(void);
    };
    

    Implement the Commit method in the ATL classes derived from CPropBase like this -

    HRESULT CPropObj1::Commit(void)
    {
    	return CPropBase::Commit();
    }
    Depending on how you have actually structured your classes and inheritance you could also derive CPropBase from IPropertyStore.


    • Edited by RLWA32 Monday, October 21, 2019 3:08 PM added comment
    • Marked as answer by amt528 Tuesday, October 22, 2019 2:47 PM
    Monday, October 21, 2019 2:49 PM
  • You really should post the header files containing your class declarations as well as the idl file so we get a complete understanding of what you have done.

    Also, exactly what linker error do you receive?

    Monday, October 21, 2019 3:27 PM
  • A base class doesn't override a virtual method on its sibling base class; only a derived class can so override. So, just deriving from IPropertyStore and your helper class (say, CCommitImpl) side by side is not enough.

    You could have the property handler - the class that derives from both IPropertyStore and CCommitImpl - to implement Commit and simply delegate it to CCommitImpl, as RLWA32 shows. Or, you could have CCommitImpl derive from IPropertyStore and your property handler derive from CCommitImpl.


    Igor Tandetnik

    Monday, October 21, 2019 6:43 PM