Начальная проблема C ++; невозможно создать экземпляр абстрактного класса (C2259 в VS) - PullRequest
2 голосов
/ 30 марта 2009

Я пытаюсь создать конкретный экземпляр COM-интерфейса IAudioEvents (доступно в Vista и более поздних версиях). Это мой первый опыт программирования COM, поэтому я, вероятно, просто делаю что-то глупое здесь. В любом случае следующий код не может быть скомпилирован с «C2259: 'AudioEndpointVolumeNotifierImpl': невозможно создать экземпляр абстрактного класса".

Определение класса (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;
    }
};

Соответствующий .cpp:

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

    return S_OK;
}

Сбой в экземпляре IClassFactory для следующего кода:

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

Хорошая часть этого кода взята из некоторых руководств (в частности, IUnknown). Я пока не ожидаю, что этот код будет работать, но я не понимаю, почему он не компилируется.

Спасибо.

Ответы [ 3 ]

8 голосов
/ 30 марта 2009

Как ни странно, хотя OnIconPathChanged здесь описывается как параметр LPWCHAR:

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

Это показано с помощью LPCWSTR в следующем примере:

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

Один из них, вероятно, неправильный; если мы предположим, что это первое и что метод на самом деле принимает LPCWSTR (что в любом случае имеет больше смысла с учетом контекста), это объясняет вашу ошибку Я бы попробовал изменить ваше объявление на

HRESULT STDMETHODCALLTYPE OnIconPathChanged(LPCWSTR NewIconPath, LPCGUID EventContext){return S_OK;}
7 голосов
/ 30 марта 2009

В дополнение к ответу Эрика Мелски (так как вы сказали, что вы новичок, я предположил, что его ответ вам не будет ясен):

Причина, по которой вы получаете эту ошибку, заключается в том, что AudioEndpointVolumeNotifierImpl является абстрактным классом, что означает, что он имеет чисто виртуальные методы, либо непосредственно определенные в классе, либо унаследованные от базового класса.

В вашем случае это явно последнее.

То, что вы хотите сделать, это реализовать унаследованные чисто виртуальные методы, что вы пытались сделать, но если сигнатура методов не одинакова, вы просто определяете перегрузку и оставляете базовый чисто виртуальный метод неизменным. А твой класс все еще абстрактный. Отсюда и сообщение об ошибке.

2 голосов
/ 19 апреля 2012

Когда вы получаете эту ошибку, вы можете часто искать в консоли вывода (т.е. не в списке ошибок) «из-за следующих членов:», и вы увидите, что делает класс абстрактным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...