Здравствуйте, Nine, Вы писали:
N>Всем привет!. N>Если кто знает подскажите чем отличаются CComPtr и CComQIPtr?
Перед тем как отправить сообщение в форум, рекомендуется нажать кнопку "Найти ответ" — по этой теме выводится 96 ссылок.
Ну да ладно. CComQIPtr выполняет неявный вызов QueryInterface при присваивании интерфейсу другого типа.
N>И что за жуть здесь написана: N>CComPtr< IGraphBuilder > m_pGraph; N>CComQIPtr< IVideoWindow, &IID_IVideoWindow > pWindow = m_pGraph;
Аналог:
CComPtr< IGraphBuilder > m_pGraph;
CComPtr< IVideoWindow> pWindow;
if(FAILED(m_pGraph->QueryInterface(&pWindow)) // CComPtr::QueryInterface типизирован, IID не требуется
pWindow = 0;
P.S.
И еще, раз такая пьянка пошла:
у меня есть MSDN, но никака не могу найти сколь более обширной статьи по использованию этих двух классов.
Если знаете — подскажите. А если нет, то еще вопрос:
CComPtr< ISampleGrabber > m_pGrabber;
m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );//???
//я так понимаю, что m_pGrabber передается конструктору в кач. параметра, но что это означает я так и не нашел.
Здравствуйте, Nine, Вы писали:
N>1.Является ли сл. код аналогом предыдущего:
N>----------------------------------------------- N>IGraphBuilder * m_pGraph; N>IVideoWindow * pWindow;
N>CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,IID_IGraphBuilder, (void **) &pGraph); N>m_pGraph->QueryInterface(IID_IVideoWindow, (LPVOID *) &pWindow); N>-----------------------------------------------
Почти является. Существенная разница: при выходе из области видимости классы CComPtr CComQIPtr сами вызовут Release(), а в данном примере нужно не забыть сделать это самостоятельно.
Кстати, если уж мы о DirectShow, маленький оффтопик: рекомендую установить DirectX Debug Runtime — при завершении программы будет выдаваться предупреждение обо всех "неубитых" объектах.
Еще одно замечание: в этом форуме есть тэги для оформления кода — с ними читать код гораздо удобнее.
N>2.В вашем ответе, разве m_pGraph не нужно создавать ф-ей CoCreateInstance???
N>CComPtr< IGraphBuilder > m_pGraph; N>CComPtr< IVideoWindow> pWindow; N>if(FAILED(m_pGraph->QueryInterface(&pWindow)) N> pWindow = 0;
Как-то создавать, конечно, нужно. Я привел эквивалент для данного кусочка:
, в котором тоже не было создания. Кстати, у классов *Ptr есть более удобный метод CoCreateInstance(), пользоваться рекомендуется им.
N>CComPtr< ISampleGrabber > m_pGrabber; N>m_pGrabber.CoCreateInstance( CLSID_SampleGrabber ); N>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );//??? N>//я так понимаю, что m_pGrabber передается конструктору в кач. параметра, но что это означает я так и не нашел.
То же самое. Создается "умный указатель" на интерфейс IBaseFilter путем вызова QueryInterface в конструкторе CComQIPtr.
N>>CComPtr< ISampleGrabber > m_pGrabber; N>>m_pGrabber.CoCreateInstance( CLSID_SampleGrabber ); N>>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );//??? N>>//я так понимаю, что m_pGrabber передается конструктору в кач. параметра, но что это означает я так и не нашел. R>То же самое. Создается "умный указатель" на интерфейс IBaseFilter путем вызова QueryInterface в конструкторе CComQIPtr.
Так что жеж, это всего лишь прихоть использовать
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
вместо
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase = m_pGrabber;
P.S.
Спасибо за ответы. Постепенно начинаю втыкать. не мучал бы вопросами, но поиск на сайте пока не работает,
а ждать нет времени.
N>Так что жеж, это всего лишь прихоть использовать N>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber ); N>вместо N>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase = m_pGrabber;
эквивалетнты. RB>В обоих случаях будет вызван конструктор с параметром.
Последнее уточнение, хотя это уже относится к языку C++. В данном случае, эти две записи действительно эквивалентны — это две формы вызова конструктора. Но небольшая разница между ними все-таки есть. Если бы конструктор CComQIPtr был объявлен с ключевым словом explicit, второе выражение бы не скомпилировалось.
эквивалетнты. RB>>В обоих случаях будет вызван конструктор с параметром.
R>Последнее уточнение, хотя это уже относится к языку C++. В данном случае, эти две записи действительно эквивалентны — это две формы вызова конструктора. Но небольшая разница между ними все-таки есть. Если бы конструктор CComQIPtr был объявлен с ключевым словом explicit, второе выражение бы не скомпилировалось.
Раз уж пошли учточнения , то
-опрация присваивания()
и еще есть огромный недостаток у этого умного указателя- Release() там открытый,т.е. может случится так что уничтоженный объект вручную будет убиваться в деструкторе
V> просто напросто вызывает конструктор копирования, а
Ошибка. Не конструктор копирования, а конструктор вообще, так как m_pGrabber не является эквивалентным типом для CComQIPtr< IBaseFilter >. На этом и построен принцип CComQIPtr — в конструкторе с указателем на другой интерфейс вызвать QueryInterface.
Вот как реализован конструктор копирования:
V> -опрация присваивания()
Ошибка! Это другой синтаксис вызова конструктора. Вот из-за того, что такую форму конструктора часто путают с операцией присваивания, и ввели дополнительное ключевое слово explicit. При описании конструктора с этим спецификатором его нельзя будет вызывать в таком виде, о чем я и говорил в предыдущем сообщении.
V>и еще есть огромный недостаток у этого умного указателя- Release() там открытый,т.е. может случится так что уничтоженный объект вручную будет убиваться в деструкторе
Ошибка! Эти классы в operator-> возвращают не "голый" интерфейс, а специальный класс
template <class T>
class _NoAddRefReleaseOnCComPtr : public T
{
private:
STDMETHOD_(ULONG, AddRef)()=0;
STDMETHOD_(ULONG, Release)()=0;
};
В котором два этих метода закрыты. То есть вы не сможете вызвать Release() так:
pGrabBase->Release();
Ну а то, что у них есть служебный метод Release, так это по необходимости. Вдруг придется явно управлять временем жизни объекта. И если в деструкторе кто-то "по ошибке" употребит такую форму:
Здравствуйте, retalik, Вы писали:
R>Здравствуйте, v0id, Вы писали:
R>Налицо несколько грубейших ошибок — придется опять вмешаться.
V>>Раз уж пошли учточнения , то V>>
V>> просто напросто вызывает конструктор копирования, а R>Ошибка. Не конструктор копирования, а конструктор вообще, так как m_pGrabber не является эквивалентным типом для CComQIPtr< IBaseFilter >. На этом и построен принцип CComQIPtr — в конструкторе с указателем на другой интерфейс вызвать QueryInterface. R>Вот как реализован конструктор копирования: R>
V>> -опрация присваивания() R>Ошибка! Это другой синтаксис вызова конструктора. Вот из-за того, что такую форму конструктора часто путают с операцией присваивания, и ввели дополнительное ключевое слово explicit. При описании конструктора с этим спецификатором его нельзя будет вызывать в таком виде, о чем я и говорил в предыдущем сообщении.
Если оператор не определен, то согласен V>>и еще есть огромный недостаток у этого умного указателя- Release() там открытый,т.е. может случится так что уничтоженный объект вручную будет убиваться в деструкторе R>Ошибка! Эти классы в operator-> возвращают не "голый" интерфейс, а специальный класс R>
R>template <class T>
R>class _NoAddRefReleaseOnCComPtr : public T
R>{
R> private:
R> STDMETHOD_(ULONG, AddRef)()=0;
R> STDMETHOD_(ULONG, Release)()=0;
R>};
R>
R>В котором два этих метода закрыты. То есть вы не сможете вызвать Release() так: R>
R>pGrabBase->Release();
R>
R>Ну а то, что у них есть служебный метод Release, так это по необходимости. Вдруг придется явно управлять временем жизни объекта. И если в деструкторе кто-то "по ошибке" употребит такую форму: R>
R>pGrabBase.Release();
R>
R>, то он сам себе злобный буратина.
Не понял, что подразумевается под словом служебный.Пример можете привести с управлением жизни объекта?
А можно так жутко не оверквотить? А то похоже на неуважение к другим посетителям — вынуждены продираться через километры цитат, чтобы найти две строчки ответа...
R>>Ошибка! Это другой синтаксис вызова конструктора. Вот из-за того, что такую форму конструктора часто путают с операцией присваивания, и ввели дополнительное ключевое слово explicit. При описании конструктора с этим спецификатором его нельзя будет вызывать в таком виде, о чем я и говорил в предыдущем сообщении. V>Если оператор не определен, то согласен
Программируя на C++, эту разницу нужно понимать четко. Если есть сомнения — задай вопрос в форуме C++.
V>Не понял, что подразумевается под словом служебный.Пример можете привести с управлением жизни объекта?
Ну такое иногда случается — например, при смешивании кода с использованием "умных указателей" и кода, написанного без учета соглашений COM. Допустим, мы сохраняем CComPtr в контейнере, который хранит "голые" интерфейсные указатели, но не вызывает AddRef — нужно увеличить счетчик ссылок самостоятельно.