dynamic_castを使わないRTTIの実装

RTTI は実行時型情報(RunTime Type Information)あるいは実行時型識別(RunTime Type Identification)と呼ばれる仕組みです
C++でこれをサポートするための構文が dynamic_cast ですが、これはC++の言語に特有の機能ですからこれをそのままC言語などから利用するには無理があります
今回はC言語などからも RTTI の仕組みを使えるようにする方法について考えてみましょう

C言語からも使えるようにするのですから、何か dynamic_cast に相当するような動作をするメソッドを提供する必要があるでしょう
そのメソッドの仕様を考えてみると次のようになるでしょうか:

  1. 型を直接指定することはできないので、何か型と一意に関連付けられた識別子を使ってクラスを指定する
  2. 指定されたクラスを基底クラスに持っていればキャストできる
  3. 基底クラス同士に関係が無くてもキャストできる
  4. 共通の基底クラスはただ1つに決まっている

最も単純な実装は次の Fig.1 ように仮想継承を使ったものになるでしょうか
Fig.1

#define classid_CSampleUnknown	0
#define classid_CSampleFoo	1
#define classid_CSampleBar	2
#define classid_CSampleFooBar	3

class CSampleUnknown {
public:
	virtual void*	DynamicCast( int	classid ){
		void*	pvObject = NULL;
		if( classid == classid_CSampleUnknown ){
			pvObject = this;
		}
		return	pvObject;
	}
	CSampleUnknown()
	{
	}
	virtual ~CSampleUnknown(){
	}
};
class CSampleFoo : virtual public CSampleUnknown {
	int m_foo;
public:
	virtual void*	DynamicCast( int	classid ){
		void*	pvObject = NULL;
		if( classid == classid_CSampleFoo ){
			pvObject = this;
		}
		else{
			pvObject = CSampleUnknown::DynamicCast( classid );
		}
		return	pvObject;
	}
	virtual int foo(){
		return	m_foo;
	}
	CSampleFoo( int	foo ):
	CSampleUnknown(),
	m_foo(foo)
	{
	}
	virtual ~CSampleFoo(){
	}
};
class CSampleBar : virtual public CSampleUnknown {
	int m_bar;
public:
	virtual void*	DynamicCast( int	classid ){
		void*	pvObject = NULL;
		if( classid == classid_CSampleBar ){
			pvObject = this;
		}
		else{
			pvObject = CSampleUnknown::DynamicCast( classid );
		}
		return	pvObject;
	}
	virtual int bar(){
		return	m_bar;
	}
	CSampleBar( int	bar ):
	CSampleUnknown(),
	m_bar(bar)
	{
	}
	virtual ~CSampleBar(){
	}
};
class CSampleFooBar : virtual public CSampleFoo, virtual public CSampleBar {
public:
	virtual void*	DynamicCast( int	classid ){
		void*	pvObject = NULL;
		if( classid == classid_CSampleFooBar ){
			pvObject = this;
		}
		else{
			pvObject = CSampleFoo::DynamicCast( classid );
			if( !pvObject )
				pvObject = CSampleBar::DynamicCast( classid );
		}
		return	pvObject;
	}
	CSampleFooBar( int foo, int	bar ):
	CSampleFoo(foo),
	CSampleBar(bar)
	{
	}
	virtual ~CSampleFooBar(){
	}
};

使用例:

CSampleFooBar*	pFooBar = new CSampleFooBar( 123, 456 );
CSampleFoo* pFoo = ( CSampleFoo* )pFooBar->DynamicCast( classid_CSampleFoo );
CSampleBar* pBar = ( CSampleBar* )pFooBar->DynamicCast( classid_CSampleBar );
CSampleFoo* pFoo2 = ( CSampleFoo* )pBar->DynamicCast( classid_CSampleFoo );
CSampleBar* pBar2 = ( CSampleBar* )pFoo->DynamicCast( classid_CSampleBar );
CSampleUnknown* pUnknownFoo = ( CSampleUnknown* )pFoo->DynamicCast( classid_CSampleUnknown );
CSampleUnknown* pUnknownBar = ( CSampleUnknown* )pBar->DynamicCast( classid_CSampleUnknown );
CSampleUnknown* pUnknown = pFooBar->DynamicCast( classid_CSampleUnknown );
printf( "pFooBar     = 0x%p, foo = %3d, bar = %d\n", pFooBar, pFooBar->foo(), pFooBar->bar());
printf( "pFoo        = 0x%p, foo = %3d\n", pFoo, pFoo ? pFoo->foo() : 0 );
printf( "pBar        = 0x%p, bar = %3d\n", pBar, pBar ? pBar->bar() : 0 );
printf( "pFoo2       = 0x%p, foo = %3d\n", pFoo2, pFoo2 ? pFoo2->foo() : 0 );
printf( "pBar2       = 0x%p, bar = %3d\n", pBar2, pBar2 ? pBar2->bar() : 0 );
printf( "pUnknownFoo = 0x%p, pUnknownFoo->AddRef() = %d\n", pUnknownFoo, pUnknownFoo ? pUnknownFoo->AddRef() : 0 );
printf( "pUnknownBar = 0x%p, pUnknownBar->AddRef() = %d\n", pUnknownBar, pUnknownBar ? pUnknownBar->AddRef() : 0 );
printf( "pUnknown    = 0x%p, pUnknown->AddRef()    = %d\n", pUnknown, pUnknown ? pUnknown->AddRef() : 0 );
printf( "pFooBar->AddRef() = %d\n", pFooBar->AddRef());

出力の例:

pFooBar	  = 0x01091B98, foo = 123, bar = 456
pFoo        = 0x01091BA4, foo = 123
pBar        = 0x01091BB0, bar = 456
pFoo2       = 0x01091BA4, foo = 123
pBar2       = 0x01091BB0, bar = 456
pUnknownFoo = 0x01091B9C, pUnknownFoo->AddRef() = 2
pUnknownBar = 0x01091B9C, pUnknownBar->AddRef() = 3
pUnknown    = 0x01091B9C, pUnknown->AddRef()    = 4
pFooBar->AddRef() = 5

動作としてはこれでよさそうです
しかしC言語から使うことを考えるとベタなC++のクラスのままではダメですね
そこでC言語からも使えるように考えてみると次のような注意が必要でしょう:

  1. 抽象基底クラスを使う。ただし、抽象基底クラスには多重継承を使わない
  2. 仮想継承を使わない

これを踏まえてまず抽象基底クラスを考えると Fig.2 のようになるでしょうか
Fig.2

#define classid_ISampleUnknown	0
#define classid_ISampleFoo	1
#define classid_ISampleBar	2
#define classid_ISampleFooBar	3

struct ISampleUnknown {
	virtual void*	DynamicCast( int	classid ) = 0;
	virtual unsigned long	AddRef() = 0;
	virtual unsigned long	Release() = 0;
};
struct ISampleFoo : public ISampleUnknown {
	virtual int foo() = 0;
};
struct ISampleBar : public ISampleUnknown {
	virtual int bar() = 0;
};
struct ISampleFooBar : public ISampleUnknown {
	virtual int foo() = 0;
	virtual int bar() = 0;
};

ではこれを実装してみましょう
Fig.3

class CSampleFooBar : public ISampleFooBar, public ISampleFoo, public ISampleBar {
	unsigned long	m_cRef;
	int m_foo;
	int m_bar;
public:
	virtual void*	DynamicCast( int classid ){
		void*	pvObject = NULL;
		if( classid == classid_IUnknown ){
			// 別に ISampleFooBar じゃなくて ISampleFoo でも ISampleBar でも同じ。
			pvObject = ( ISampleUnknown* )( ISampleFooBar* )this;
		}
		else if( classid == classid_ISampleFooBar ){
			pvObject = ( ISampleFooBar* )this;
		}
		else if( classid == classid_ISampleFoo ){
			pvObject = ( ISampleFoo* )this;
		}
		else if( classid == classid_ISampleBar ){
			pvObject = ( ISampleBar* )this;
		}
		return	pvObject;
	}
	virtual unsigned long	AddRef(){
		return	++m_cRef;
	}
	virtual unsigned long	Release(){
		if( --m_cRef == 0 ){
			delete this;
			return	0;
		}
		return	m_cRef;
	}
	virtual int foo(){
		return	m_foo;
	}
	virtual int bar(){
		return	m_bar;
	}
	CSampleFooBar( int	foo ):
	m_cRef(1),
	m_foo(foo),
	m_bar(bar)
	{
	}
	virtual ~CSampleFooBar(){
	}
};

使用例:

ISampleFooBar*	pFooBar = new CSampleFooBar( 123, 456 );
ISampleFoo* pFoo = ( CSampleFoo* )pFooBar->DynamicCast( classid_ISampleFoo );
ISampleBar* pBar = ( CSampleBar* )pFooBar->DynamicCast( classid_ISampleBar );
ISampleFoo* pFoo2 = ( CSampleFoo* )pBar->DynamicCast( classid_ISampleFoo );
ISampleBar* pBar2 = ( CSampleBar* )pFoo->DynamicCast( classid_ISampleBar );
ISampleUnknown* pUnknownFoo = ( CSampleUnknown* )pFoo->DynamicCast( classid_ISampleUnknown );
ISampleUnknown* pUnknownBar = ( CSampleUnknown* )pBar->DynamicCast( classid_ISampleUnknown );
ISampleUnknown* pUnknown = pFooBar->DynamicCast( classid_ISampleUnknown );
printf( "pFooBar     = 0x%p, foo = %3d, bar = %d\n", pFooBar, pFooBar->foo(), pFooBar->bar());
printf( "pFoo        = 0x%p, foo = %3d\n", pFoo, pFoo ? pFoo->foo() : 0 );
printf( "pBar        = 0x%p, bar = %3d\n", pBar, pBar ? pBar->bar() : 0 );
printf( "pFoo2       = 0x%p, foo = %3d\n", pFoo2, pFoo2 ? pFoo2->foo() : 0 );
printf( "pBar2       = 0x%p, bar = %3d\n", pBar2, pBar2 ? pBar2->bar() : 0 );
printf( "pUnknownFoo = 0x%p, pUnknownFoo->AddRef() = %d\n", pUnknownFoo, pUnknownFoo ? pUnknownFoo->AddRef() : 0 );
printf( "pUnknownBar = 0x%p, pUnknownBar->AddRef() = %d\n", pUnknownBar, pUnknownBar ? pUnknownBar->AddRef() : 0 );
printf( "pUnknown    = 0x%p, pUnknown->AddRef()    = %d\n", pUnknown, pUnknown ? pUnknown->AddRef() : 0 );
printf( "pFooBar->AddRef() = %d\n", pFooBar->AddRef());

出力の例

pFooBar	  = 0x01091B98, foo = 123, bar = 456
pFoo        = 0x01091BA4, foo = 123
pBar        = 0x01091BB0, bar = 456
pFoo2       = 0x01091BA4, foo = 123
pBar2       = 0x01091BB0, bar = 456
pUnknownFoo = 0x01091B9C, pUnknownFoo->AddRef() = 2
pUnknownBar = 0x01091B9C, pUnknownBar->AddRef() = 3
pUnknown    = 0x01091B9C, pUnknown->AddRef()    = 4
pFooBar->AddRef() = 5

このような感じになるでしょうか
Fig.1 のように基底クラスの実装を別にすると、それは Fig.4 のようになります
Fig.4

class CSampleFoo : public ISampleFoo {
	unsigned long	m_cRef;
	int m_foo;
public:
	virtual void*	DynamicCast( int classid ){
		void*	pvObject = NULL;
		if( classid == classid_IUnknown ){
			pvObject = ( ISampleUnknown* )( ISampleFooBar* )this;
		}
		else if( classid == classid_ISampleFoo ){
			pvObject = ( ISampleFooBar* )this;
		}
		return	pvObject;
	}
	virtual unsigned long	AddRef(){
		return	++m_cRef;
	}
	virtual unsigned long	Release(){
		if( --m_cRef == 0 ){
			delete this;
			return	0;
		}
		return	m_cRef;
	}
	virtual int foo(){
		return	m_foo;
	}
	CSampleFoo( int foo ):
	m_cRef(1),
	m_foo(foo)
	{
	}
	virtual ~CSampleFoo(){
	}
};
class CSampleBar : public ISampleBar {
	unsigned long	m_cRef;
	int m_bar;
public:
	virtual void*	DynamicCast( int classid ){
		void*	pvObject = NULL;
		if( classid == classid_IUnknown ){
			pvObject = ( ISampleUnknown* )( ISampleFooBar* )this;
		}
		else if( classid == classid_ISampleBar ){
			pvObject = ( ISampleFooBar* )this;
		}
		return	pvObject;
	}
	virtual unsigned long	AddRef(){
		return	++m_cRef;
	}
	virtual unsigned long	Release(){
		if( --m_cRef == 0 ){
			delete this;
			return	0;
		}
		return	m_cRef;
	}
	virtual int bar(){
		return	m_bar;
	}
	CSampleBar( int bar ):
	m_cRef(1),
	m_bar(bar)
	{
	}
	virtual ~CSampleBar(){
	}
};
class CSampleFooBar : public ISampleFooBar, public CSampleFoo, public CSampleBar {
	unsigned long	m_cRef;
public:
	virtual void*	DynamicCast( int classid ){
		void*	pvObject = NULL;
		if( classid == classid_IUnknown ){
			pvObject = ( ISampleUnknown* )( ISampleFooBar* )this;
		}
		else if( classid == classid_ISampleFooBar ){
			pvObject = ( ISampleFooBar* )this;
		}
		else{
			pvObject = CSampleFoo::DynamicCast( classid );
			if( !pvObject ){
				pvObject = CSampleBar::DynamicCast( classid );
			}
		}
		return	pvObject;
	}
	virtual unsigned long	AddRef(){
		// 別に自前でやらなくても CSampleFoo か CSampleBar の実装を使っても同じ。
		return	++m_cRef;
	}
	virtual unsigned long	Release(){
		// 別に自前でやらなくても CSampleFoo か CSampleBar の実装を使っても同じ。
		if( --m_cRef == 0 ){
			delete this;
			return	0;
		}
		return	m_cRef;
	}
	virtual int foo(){
		return	CSampleFoo::foo();
	}
	virtual int bar(){
		return	CSampleBar::bar();
	}
	CSampleFooBar( int	foo ):
	m_cRef(1),
	CSampleFoo(foo),
	CSampleBar(bar)
	{
	}
	virtual ~CSampleFooBar(){
	}
};

使用例:

ISampleFooBar*	pFooBar = new CSampleFooBar( 123, 456 );
ISampleFoo* pFoo = ( CSampleFoo* )pFooBar->DynamicCast( classid_ISampleFoo );
ISampleBar* pBar = ( CSampleBar* )pFooBar->DynamicCast( classid_ISampleBar );
ISampleFoo* pFoo2 = ( CSampleFoo* )pBar->DynamicCast( classid_ISampleFoo );
ISampleBar* pBar2 = ( CSampleBar* )pFoo->DynamicCast( classid_ISampleBar );
ISampleUnknown* pUnknownFoo = ( CSampleUnknown* )pFoo->DynamicCast( classid_ISampleUnknown );
ISampleUnknown* pUnknownBar = ( CSampleUnknown* )pBar->DynamicCast( classid_ISampleUnknown );
ISampleUnknown* pUnknown = pFooBar->DynamicCast( classid_ISampleUnknown );
printf( "pFooBar     = 0x%p, foo = %3d, bar = %d\n", pFooBar, pFooBar->foo(), pFooBar->bar());
printf( "pFoo        = 0x%p, foo = %3d\n", pFoo, pFoo ? pFoo->foo() : 0 );
printf( "pBar        = 0x%p, bar = %3d\n", pBar, pBar ? pBar->bar() : 0 );
printf( "pFoo2       = 0x%p, foo = %3d\n", pFoo2, pFoo2 ? pFoo2->foo() : 0 );
printf( "pBar2       = 0x%p, bar = %3d\n", pBar2, pBar2 ? pBar2->bar() : 0 );
printf( "pUnknownFoo = 0x%p, pUnknownFoo->AddRef() = %d\n", pUnknownFoo, pUnknownFoo ? pUnknownFoo->AddRef() : 0 );
printf( "pUnknownBar = 0x%p, pUnknownBar->AddRef() = %d\n", pUnknownBar, pUnknownBar ? pUnknownBar->AddRef() : 0 );
printf( "pUnknown    = 0x%p, pUnknown->AddRef()    = %d\n", pUnknown, pUnknown ? pUnknown->AddRef() : 0 );
printf( "pFooBar->AddRef() = %d\n", pFooBar->AddRef());

出力の例:

pFooBar	  = 0x01091B98, foo = 123, bar = 456
pFoo        = 0x01091BA4, foo = 123
pBar        = 0x01091BB0, bar = 456
pFoo2       = 0x01091BA4, foo = 123
pBar2       = 0x01091BB0, bar = 456
pUnknownFoo = 0x01091B9C, pUnknownFoo->AddRef() = 2
pUnknownBar = 0x01091B9C, pUnknownBar->AddRef() = 3
pUnknown    = 0x01091B9C, pUnknown->AddRef()    = 4
pFooBar->AddRef() = 5

ただ、このように基底クラスの実装を別に書くとなると、この例の ISampleUnknown のような共通の基底クラスの実装をいくつも書く必要が出てきて、少し面倒ですね
このような場合には、テンプレートクラスを基底クラスに使うと少し楽になりますよ
Fig.5

template<class T,int _classid> class CSampleUnknown : public T {
protected:
	ISampleUnknown* m_pUnkOuter;
	unsigned long	m_cRef;
public:
	virtual void*	DynamicCast( int	classid ){
		void*	pvObject = NULL;
		if( classid == classid_ISampleUnknown ){
			pvObject = ( ISampleUnknown* )this;
		}
		else if( classid == _classid ){
			pvObject = ( T* )this;
		}
		else if( m_pUnkOuter ){
			pvObject = m_pUnkOuter->DynamicCast( classid );
		}
		return	pvObject;
	}
	virtual unsigned long	AddRef(){
		return	++m_cRef;
	}
	virtual unsigned long	Release(){
		if( --m_cRef == 0 ){
			delete this;
			return	0;
		}
		return	m_cRef;
	}
	CSampleUnknown( ISampleUnknown* pUnkOuter = NULL ):
	m_pUnkOuter(pUnkOuter),
	m_cRef(1)
	{
		if( m_pUnkOuter ){
			m_pUnkOuter->AddRef();
		}
	}
	virtual ~CSampleUnknown(){
		if( m_pUnkOuter ){
			m_pUnkOuter->Release();
			m_pUnkOuter = NULL;
		}
	}
};
class CSampleFoo : public CSampleUnknown<ISampleFoo,classid_ISampleFoo> {
	int m_foo;
public:
	virtual int foo(){
		return	m_foo;
	}
	CSampleFoo( int foo, ISampleUnknown*	pUnkOuter = NULL ):
	CSampleUnknown<ISampleFoo,classid_ISampleFoo>(pUnkOuter),
	m_foo(foo)
	{
	}
	virtual ~CSampleFoo(){
	}
};
class CSampleBar : public CSampleUnknown<ISampleBar,classid_ISampleBar> {
	int m_bar;
public:
	virtual int bar(){
		return	m_bar;
	}
	CSampleBar( int bar, ISampleUnknown*	pUnkOuter = NULL ):
	CSampleUnknown<ISampleBar,classid_ISampleBar>(pUnkOuter),
	m_bar(bar)
	{
	}
	virtual ~CSampleBar(){
	}
};
class CSampleFooBar : public CSampleUnknown<ISampleFooBar,classid_ISampleFooBar>, public CSampleFoo, public CSampleBar {
public:
	virtual void*	DynamicCast( int classid ){
		void*	pvObject = CSampleUnknown<ISampleFooBar,classid_ISampleFooBar>::DynamicCast( classid );
		if( !pvObject ){
			pvObject = CSampleFoo::DynamicCast( classid );
			if( !pvObject ){
				pvObject = CSampleBar::DynamicCast( classid );
			}
		}
		return	pvObject;
	}
	// テンプレートクラスを基底クラスに使っているので書いていないけれども、
	// 実際には CSampleUnknown<ISampleFooBar,classid_ISampleFooBar> の実装がインライン展開されるので
	// こう(↓)書いてあるのと同じ。
	/*
	virtual unsigned long	AddRef(){
		return	CSampleUnknown<ISampleFooBar,classid_ISampleFooBar>::AddRef();
	}
	virtual unsigned long	Release(){
		return	CSampleUnknown<ISampleFooBar,classid_ISampleFooBar>::Release();
	}
	*/
	// 本当にこう(↑)書いても文法的も機能的にも問題ないようです。
	virtual int foo(){
		return	CSampleFoo::foo();
	}
	virtual int bar(){
		return	CSampleBar::bar();
	}
	CSampleFooBar( int	foo, int	bar ):
	CSampleUnknown<ISampleFooBar,classid_ISampleFooBar>(),
	CSampleFoo(foo),
	CSampleBar(bar)
	{
	}
	virtual ~CSampleFooBar(){
	}
};

使用例:

ISampleFooBar*	pFooBar = new CSampleFooBar( 123, 456 );
ISampleFoo* pFoo = ( CSampleFoo* )pFooBar->DynamicCast( classid_ISampleFoo );
ISampleBar* pBar = ( CSampleBar* )pFooBar->DynamicCast( classid_ISampleBar );
ISampleFoo* pFoo2 = ( CSampleFoo* )pBar->DynamicCast( classid_ISampleFoo );
ISampleBar* pBar2 = ( CSampleBar* )pFoo->DynamicCast( classid_ISampleBar );
ISampleUnknown* pUnknownFoo = ( CSampleUnknown* )pFoo->DynamicCast( classid_ISampleUnknown );
ISampleUnknown* pUnknownBar = ( CSampleUnknown* )pBar->DynamicCast( classid_ISampleUnknown );
ISampleUnknown* pUnknown = pFooBar->DynamicCast( classid_ISampleUnknown );
printf( "pFooBar     = 0x%p, foo = %3d, bar = %d\n", pFooBar, pFooBar->foo(), pFooBar->bar());
printf( "pFoo        = 0x%p, foo = %3d\n", pFoo, pFoo ? pFoo->foo() : 0 );
printf( "pBar        = 0x%p, bar = %3d\n", pBar, pBar ? pBar->bar() : 0 );
printf( "pFoo2       = 0x%p, foo = %3d\n", pFoo2, pFoo2 ? pFoo2->foo() : 0 );
printf( "pBar2       = 0x%p, bar = %3d\n", pBar2, pBar2 ? pBar2->bar() : 0 );
printf( "pUnknownFoo = 0x%p, pUnknownFoo->AddRef() = %d\n", pUnknownFoo, pUnknownFoo ? pUnknownFoo->AddRef() : 0 );
printf( "pUnknownBar = 0x%p, pUnknownBar->AddRef() = %d\n", pUnknownBar, pUnknownBar ? pUnknownBar->AddRef() : 0 );
printf( "pUnknown    = 0x%p, pUnknown->AddRef()    = %d\n", pUnknown, pUnknown ? pUnknown->AddRef() : 0 );
printf( "pFooBar->AddRef() = %d\n", pFooBar->AddRef());

出力の例:

pFooBar	     = 0x01091B98, foo = 123, bar = 456
pFoo        = 0x01091BA4, foo = 123
pBar        = 0x01091BB0, bar = 456
pFoo2       = 0x01091BA4, foo = 123
pBar2       = 0x01091BB0, bar = 456
pUnknownFoo = 0x01091B9C, pUnknownFoo->AddRef() = 2
pUnknownBar = 0x01091B9C, pUnknownBar->AddRef() = 3
pUnknown    = 0x01091B9C, pUnknown->AddRef()    = 4
pFooBar->AddRef() = 5

どうでしょうか、これでC++の RTTI や仮想継承を使わずに自前で RTTI を実装できました
これならC++からもC言語などからも使うことができますし、使い勝手の面でも dynamic_cast と然程変わりありませんね

ところで、この例で使った ISampleUnknownインターフェイスはリファレンスカウンタを持っていますから、DynamicCast でインスタンスのコピーを作ったときにはリファレンスカウンタを増やすのもいいかもしれません
そのようなものを考えるとそれは Fig.6 のようになるでしょうか
Fig.6

struct ISampleUnknown {
	virtual bool	DynamicCast( int	classid, void** ppvObject ) = 0;
	virtual unsigned long	AddRef() = 0;
	virtual unsigned long	Release() = 0;
};

template<class T,int _classid> class CSampleUnknown : public T {
protected:
	ISampleUnknown* m_pUnkOuter;
	unsigned long	m_cRef;
public:
	virtual bool	DynamicCast( int	classid, void** ppvObject ){
		if( ppvObject ){
			*ppvObject = NULL;
		}
		bool	fSuccess = true;
		if( !ppvObject ){
			fSuccess = false;
		}
		if( fSuccess ){
			if( classid == classid_ISampleUnknown ){
				AddRef();
				*ppvObject = ( ISampleUnknown* )this;
			}
			else if( classid == _classid ){
				AddRef();
				*ppvObject = ( T* )this;
			}
			else if( m_pUnkOuter ){
				fSuccess = m_pUnkOuter->DynamicCast( classid, ppvObject );
			}
			else{
				fSuccess = false;
			}
		}
		return	fSuccess;
	}
	virtual unsigned long	AddRef(){
		return	++m_cRef;
	}
	virtual unsigned long	Release(){
		if( --m_cRef == 0 ){
			delete this;
			return	0;
		}
		return	m_cRef;
	}
	CSampleUnknown( ISampleUnknown* pUnkOuter = NULL ):
	m_pUnkOuter(pUnkOuter),
	m_cRef(1)
	{
		if( m_pUnkOuter ){
			m_pUnkOuter->AddRef();
		}
	}
	virtual ~CSampleUnknown(){
		if( m_pUnkOuter ){
			m_pUnkOuter->Release();
			m_pUnkOuter = NULL;
		}
	}
};

さて、ここで
もうお気付きの方もいらっしゃると思いますが、この ISampleUnknownインターフェイスの DynamicCastメソッドの名前を QueryInterface と変えてみるとどうでしょうか
そうです。これでは全く COM の IUnknownインターフェイスそのものではないですか
そうなんです。これは単なる見た目だけの問題ではなく本当に IUnknownそのものなのです
とかく分からないと言われがちな IUnknown::QueryInterface なのですが、単なる dynamic_cast だと考えてみれば簡単ではないでしょうか
また dynamic_cast と考えることで「QueryInterface の返すオブジェクトは必ず this でなければいけない」といった決まりにも納得がいくのではないでしょうか

というところで、今回はこの辺で