tags:

views:

2934

answers:

2

I'm attempting to create a concrete instance of the IAudioEvents COM interface (available in Vista and later). This is my first foray into COM programming, so I'm probably just doing something stupid here. Anyway, the following code fails to compile with "C2259: 'AudioEndpointVolumeNotifierImpl' : cannot instantiate abstract class".

Class Definiton (AudioEndpointVolumeNotifierImpl.h):

class AudioEndpointVolumeNotifierImpl : public IAudioSessionEvents
{
private:
    LONG _cRef;

public:
    AudioEndpointVolumeNotifierImpl() : _cRef(1){}
    ~AudioEndpointVolumeNotifierImpl(){}
    HRESULT STDMETHODCALLTYPE OnSimpleVolumeChanged(float NewVolume, BOOL NewMute,LPCGUID EventContext);

    HRESULT STDMETHODCALLTYPE OnChannelVolumeChanged(DWORD ChannelCount, float NewChannelVolumeArray[], DWORD ChangedChannel, LPCGUID EventContext){return S_OK;}
    HRESULT STDMETHODCALLTYPE OnDisplayNameChanged(LPCWSTR NewDisplayName, LPCGUID EventContext){return S_OK;}
    HRESULT STDMETHODCALLTYPE OnGroupingParamChanged(LPCGUID NewGroupingParam, LPCGUID EventContext){return S_OK;}
    HRESULT STDMETHODCALLTYPE OnIconPathChanged(LPWCHAR NewIconPath, LPCGUID EventContext){return S_OK;}
    HRESULT STDMETHODCALLTYPE OnSessionDisconnected(AudioSessionDisconnectReason DisconnectReason){return S_OK;}
    HRESULT STDMETHODCALLTYPE OnStateChanged(AudioSessionState NewState){ return S_OK; }

    ULONG STDMETHODCALLTYPE AddRef()
    {
        return InterlockedIncrement(&_cRef);
    }

    ULONG STDMETHODCALLTYPE Release()
    {
        ULONG ulRef = InterlockedDecrement(&_cRef);
        if (0 == ulRef)
        {
            delete this;
        }
        return ulRef;

    }

    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface)
    {
        if (IID_IUnknown == riid)
        {
            AddRef();
            *ppvInterface = (IUnknown*)this;
        }
        else if (__uuidof(IAudioSessionEvents) == riid)
        {
            AddRef();
            *ppvInterface = (IAudioSessionEvents*)this;
        }
        else
        {
            *ppvInterface = NULL;
            return E_NOINTERFACE;
        }
        return S_OK;
    }
};

Corresponding .cpp:

HRESULT STDMETHODCALLTYPE AudioEndpointVolumeNotifierImpl::OnSimpleVolumeChanged(float NewVolume, BOOL NewMute, LPCGUID EventContext)
{
    PostStatusChange(NewVolume);

    return S_OK;
}

Fails in an IClassFactory instance on the following code:

...
AudioEndpointVolumeNotifierImpl* pObject = new AudioEndpointVolumeNotifierImpl();
    if (pObject == NULL)
    {
        return E_OUTOFMEMORY ;
    }
...

A good portion of this code IS lifted from some tutorials (the IUnknown stuff in particular). I'm not expecting this code to work just yet, but I can't see why it doesn't compile.

Thanks.

+8  A: 

Oddly, although OnIconPathChanged is described as taking an LPWCHAR parameter here:

http://msdn.microsoft.com/en-us/library/dd370939(VS.85).aspx

It is shown taking an LPCWSTR in the example here:

http://msdn.microsoft.com/en-us/library/dd370797(VS.85).aspx

One of these is probably wrong; if we assume it is the former, and that the method actually takes an LPCWSTR (which makes more sense given the context anyway), that would explain your error. I would try changing your declaration to

HRESULT STDMETHODCALLTYPE OnIconPathChanged(LPCWSTR NewIconPath, LPCGUID EventContext){return S_OK;}

Hope that helps,

Eric Melski

Eric Melski
+6  A: 

In addition to Eric Melski's answer (since you said you were a beginner, i assumed his answer would not be clear to you):

The reason why you get this error is because AudioEndpointVolumeNotifierImpl is an abstract class, which means that it has pure virtual methods, either directly defined in the class, or inherited from base class.

In your case, it's clearly the latter.

What you want to do is implement inherited pure virtual methods, which you have tried to do, but if the signature of the methods are not the same, you are simply defining an overload, and leaving the base pure virtual method unchanged. And your class is still abstract. Hence the error message.

Benoît