2015-01-20 2 views
2

У меня есть класс, производный (public) от IUnknown, определение которого (из файла include/unknwnbase.h в MinGW 4.9.2) счетный ниже:Отсутствует виртуальный деструктор в базовом классе интерфейса?

extern "C++" { 
    MIDL_INTERFACE("00000000-0000-0000-C000-000000000046") 
    IUnknown { 
    public: 
    BEGIN_INTERFACE 
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) = 0; 
    virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0; 
    virtual ULONG STDMETHODCALLTYPE Release(void) = 0; 

    template<class Q> 
    HRESULT STDMETHODCALLTYPE QueryInterface(Q **pp) { 
     return QueryInterface(__uuidof(Q), (void **)pp); 
    } 
    END_INTERFACE 
    }; 
} 

Когда я компилирую производный класс, я получаю следующее предупреждение (которое в OpenCV проект рассматривается как ошибки):

базового класс структура IUnknown 'имеет доступный невиртуальный деструктор [-Werror = невиртуальный-dtor]

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

+0

Не знаете, что делают эти макросы, но попробуйте добавить пустой виртуальный деструктор? –

+0

Я думаю, он [был исправлен по-последнему] (https://github.com/Itseez/opencv/pull/3599), вы должны попробовать свежее git pull – berak

+1

@berak Я отправил ошибку :), я в курсе репозиторий и исправление, к сожалению, не помогают – Antonio

ответ

3

В контексте COM, управления жизненным циклом объектов (и связанных с ними очистки) происходит с использованием AddRef() и Release() методы IUnknown через подсчет ссылок.

Каждый объект COM имеет ссылочный счет, связанный с ним. Когда счетчик ссылок объекта достигает 0 (после того, как несколько клиентов объекта правильно вызвали Release() на некоторый указатель интерфейса COM), объект уничтожается. Другими словами, объекты COM не уничтожаются обычным способом вызова C++, например. delete на указатель базового класса (и, следовательно, требуются надлежащие virtual деструкторы в базовых классах).
(И в самом деле, вы не можете просто вызвать new для выделения COM объекта. Там больше COM машины, что требуется.)

Другими словами, когда вы закончите с указателем COM интерфейса, вы просто позвоните по телефону Release(). Поэтому нет необходимости определять виртуальные деструкторы в «базовых классах», например, интерфейс IUknown или другие COM-интерфейсы.

Итак, я подозреваю, что предупреждение является ошибкой где-то в вашей инструментальной комбинации MinGW.

Вы не предполагается изменить определение IUnknown в заголовочном файле Windows SDK вы цитируемой, ни вы не должны добавить виртуальный деструктор в пользовательских COM-интерфейсов, которые вы можете определить для ваших целей.

+0

Добавление 'virtual ~ IUnknown() {};' * кажется *, чтобы устранить проблему ... (Примечание: до тех пор, пока я отключу предварительно скомпилированные заголовки в сборке OpenCV). Что может быть причиной этого? Кажется разумным способом подчиниться правилу C++ (класс с виртуальными методами должен иметь виртуальный деструктор). Примечание. Также есть файл unknwn.h с тем же определением. Я установил определение деструктора до «END_INTERFACE» – Antonio

+1

Как указано в моем ответе, я считаю, что вы не должны добавлять виртуальных деструкторов к своим пользовательским COM-интерфейсам, и, конечно же, вы не должны изменять определение «IUnknown», добавляя виртуальный деструктор. Это не «обычный C++» _, это ** COM **, и, как я писал, вы не можете рассуждать в терминах «чистого C++» _ при работе с COM, поскольку, например, вы не можете просто 'new' COM-объект, но вам нужно иметь дело с надлежащими COM-API, такими как' CoCreateInstance() '. Также обратите внимание, что в общем случае вы не должны изменять файлы заголовков систем Windows, такие как заголовок SDK, содержащий определение 'IUnknown'. –

+0

Я вижу ... Но тогда какой правильный способ обойти эту ошибку? – Antonio