2010-06-13 9 views
5

브라우저 도우미 개체에 대해 this example code을 이해하려고합니다.C++에서 여러 COM 인터페이스를 구현하는 방법은 무엇입니까?

내부에서는 작성자가 여러 인터페이스 (IObjectWithSite, IDispatch)를 노출하는 단일 클래스를 구현합니다.

자신의 QueryInterface 함수는 다음을 수행합니다

if(riid == IID_IUnknown) *ppv = static_cast<BHO*>(this); 
else if(riid == IID_IObjectWithSite) *ppv = static_cast<IObjectWithSite*>(this); 
else if (riid == IID_IDispatch) *ppv = static_cast<IDispatch*>(this); 

나는 C의 관점에서, 인터페이스 포인터는 단지 vtable을에 대한 포인터 것을 배웠습니다. 그래서 C++이 static_cast를 사용하여 구현 된 인터페이스의 VTable을 반환 할 수 있다는 것을 의미합니다.

이 방법으로 구성된 클래스는 메모리에 VTables 묶음이 있다는 것을 의미합니까 (IObjectWithSite, IDispatch 등)? C++은 서로 다른 인터페이스 (각각 QueryInterface, AddRef 및 Release 함수가 있음)에서 이름 충돌을 어떻게 처리합니까? 각각에 대해 서로 다른 메소드를 구현할 수 있습니까?

답변

6

예, 상속 된 각 인터페이스에 대해 하나씩 여러 개의 v 테이블이 있습니다. static_cast <>이 반환합니다. 컴파일러는 상속 된 인터페이스의 공통 메소드가 공유되는지 확인하여 각 v 테이블 슬롯을 동일한 함수에 대한 포인터로 채 웁니다. 따라서 AddRef, Release, QueryInterface의 구현 만 필요합니다. 원하는대로. 이건 사고가 아니야.

코 쿠스가 과 동일한 방법으로 여러 인터페이스를 구현하는 경우에만에 동일한 구현을 제공하려는 경우에만 문제가됩니다. IConnectionPoint :: Advise() 메서드는 유명한 예제입니다. 아니면 DAdvise()입니까? 불행히도, 나는 그것이 충돌 한 것과 그것을 어떻게 해결했는지 기억하지 못한다. 그것은 ATL Internals에 의해 다루어졌다. 아주 좋은 책 btw. this 포인터 주어진 경우

다중 상속에서
+1

고마워요! 내 자신의 일부 독서 짓을하고 그것이 다른 VTables를 만들뿐만 아니라 일반적인 기능으로 다시 리디렉션하기 전에 포인터를 수정하는 "썽크"함수를 만듭니다 발견했습니다. – Martin

3

여러 vtable을 다음 형식과 같은 순서로 배열된다 (제 1 바이트를 가리킨 01)

[01] [02] [03] [04] [05] 06] [07] [08] [09] [10] [11] [12] VTableA의
[의 PTR]가 [의 PTR ++ C에서

] VTableC의 VTableB 여기서의 PTR는 단지 하나의 구현이 생성 될 다중 인터페이스 시나리오에서 함수 당 프로토 타입. 그러나 정상적인 상속 시나리오의 경우 수퍼 클래스는 사전 정의 된 구현을 가질 수 있으며 함수를 재정의하는 하위 노드는 부모와 다른 내용을 가리키는 VTables를가집니다.