Com_ptrクラスの完全実装

 以下から下をコピペすると直ぐに使えるようになります。


// Com_ptrクラス

// DirectXのインターフェイスの参照カウンタやコピーなどの問題を解決する。
// デバッグ時にはインターフェイスの使用状況をDEBUG.txtというファイル名で
// 外部に出力します。
// デバッグ時にこの機能をOFFにするには下の
// OUTPUT_INTERFACEUSAGE定数をコメントアウトしてください。

#define OUTPUT_INTERFACEUSAGE

#ifdef OUTPUT_INTERFACEUSAGE
   #if _DEBUG
   // デバッグ時にファイル出力
   #include <fstream>
   using namespace std;
   #endif
#endif



template <class T>
class Com_ptr
{
private:
   T* m_pInterface;   // インターフェイスへのポインタ

protected:
   // 参照カウンタ増加
   void AddRef(T* pInterface){
      #if _DEBUG
         // デバッグ版では参照カウントを出力する
         ULONG c = pInterface->AddRef();
         ofstream ofs;
         ofs.open("DEBUG.txt", ios::app);
         ofs << pInterface << "\t[" << c << "]" << endl;
         ofs.close();
      #else
         pInterface->AddRef();
      #endif
   }

   // 参照カウンタ減少
   void Release(T* pInterface){
      #if _DEBUG
         ULONG c = m_pInterface->Release();
         ofstream ofs;
         ofs.open("DEBUG.txt", ios::app);
         ofs << m_pInterface << "\t[" << c << "]" << endl;
         ofs.close();
      #else
         m_pInterface->Release();
      #endif
   }

public:
   // デフォルトコンストラクタ
   // コンストラクタはexplicit宣言します。
   // よってfunc(Com_ptr<IHoge> v)という関数に対して、
   // func(pIHoge)のような暗黙型変換代入は出来ません。
   // 通常、ポインタの引渡し時にすでに参照カウンタは
   // インクリメントされているので、AddRefは行いません。
   explicit Com_ptr(T* pInterface = NULL, BOOL add=FALSE){
      if(pInterface && add){
         AddRef(pInterface);
      }
      m_pInterface = pInterface;
   }

   // コピーコンストラクタ
   Com_ptr(const Com_ptr& src){
      // コピー元の参照カウンタを1つ増やす
      if(src.m_pInterface)
         AddRef(src.m_pInterface);

      // コピー
      m_pInterface = src.m_pInterface;
   }

   // デストラクタ
   virtual ~Com_ptr(){
      if(m_pInterface)
         Release(m_pInterface);
   }

   // 演算子
   // =代入演算子(明示的コピー)
   Com_ptr& operator =(const Com_ptr& src){
      // 自分のインターフェイスの参照カウンタを1つ減らす
      if(m_pInterface)
         Release(m_pInterface);

      // コピー元の参照カウンタを1つ増やす
      if(src.m_pInterface)
         AddRef(src.m_pInterface);

      // コピー
      m_pInterface = src.m_pInterface;

      return *this;
   }

   // =代入演算子(インターフェイス登録)
   void operator =(T* pInterface){
      // 自分のインターフェイスの参照カウンタを1つ減らす
      if(m_pInterface)
         Release(m_pInterface);

      // コピー
      m_pInterface = pInterface;
   }

   // !=比較演算子
   BOOL operator !=(int val){
      if(val != (int)m_pInterface)
         return TRUE;
      return FALSE;
   }

   // ==比較演算子
   BOOL operator ==(int val){
      if(val == (int)m_pInterface)
         return TRUE;
      return FALSE;
   }

// メンバ関数
   // ポインタ取得
   T* GetPtr(){return m_pInterface;}

   // ポインタのアドレスを取得
   T** GetPtrPtr(){return &m_pInterface;}

   // インターフェイス生成関数へ渡す専用関数
   T** ToCreator(){
      if(m_pInterface)
         m_pInterface->Release();

      return &m_pInterface;
   }
};