При реализации нескольких COM-интерфейсов одновременно, как выполнить обновление до IUnknown? - PullRequest
2 голосов
/ 16 ноября 2009

Предположим, что мой COM-объект реализует два или более COM-интерфейса:

class CMyClass : public IPersistFile, public IPersistStream {
};

при реализации QueryInterface () мне нужно иметь возможность вернуть указатель IUnknown *. Так как оба базовых интерфейса являются производными от IUnknown, я не могу неявно выгружать - такой выгрузка будет неясной. Для явного отката мне нужно использовать любой из двух способов:

 if( iid == __uuidof( IUnknown ) ) {
     *ppv = static_cast<IPersistFile*>( this );
     static_cast<IPersistFile*>( this )->AddRef();
     return S_OK;
 }

или

 if( iid == __uuidof( IUnknown ) ) {
     *ppv = static_cast<IPersistStream*>( this );
     static_cast<IPersistStream*>( this )->AddRef();
     return S_OK;
 }

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

Какой upcast я должен выбрать и почему?

Ответы [ 4 ]

5 голосов
/ 16 ноября 2009

Марк Рэнсом уже дал правильный ответ - любой подойдет, если он последовательный - но выбор первого имеет одно незначительное преимущество. Из-за правил компоновки, IUnknown* первого интерфейса будет указывать на начало объекта. Любой другой IUnknown* будет указывать на последующие указатели vtable в другом месте объекта. В целях отладки очень полезно знать, где в памяти начинается ано-объект.

4 голосов
/ 16 ноября 2009

Неважно, какой upcast вы используете, только то, что вы всегда используете один и тот же. Я просто выбрал бы соглашение, такое как всегда возвращать первое, объявленное в списке наследования.

0 голосов
/ 16 ноября 2009

Обычно в случаях, когда вы хотите привести к IUnknown объект с множественным наследованием от IUnknown, вы приводите его к одному из его интерфейсов, а затем приводите к IUnknown ...

0 голосов
/ 16 ноября 2009

IUknown не реализовано. Вам необходимо предоставить всю реализацию IUnknown. Таким образом, в QI IUknown вы возвращаете указатель this.

AddRef, Release и QI все реализованы вами, а не на родительском интерфейсе, так что у вас нет проблем, просто вызывайте addref, приведение не требуется.

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