- ベストアンサー
interfaceに定義するメソッドの隠蔽方法
- interfaceに定義するメソッドについて教えてください。
- 描画エンジンであるengine.dll内で、アプリから呼ばれないメソッドをインターフェイスに定義する方法を教えてください。
- 具体的には、Drawメソッドをアプリから非公開にする方法を知りたいです。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
COMの考え方を参考にするといいと思います。 サンプルを書いてみましたので読んでみてください。 ■ アプリ用ヘッダ #define __interface struct __interface IShape { virtual bool SetPos( int x, int y ) = 0; }; __interface IRender { virtual bool DrawShape( IShape* pShape ) = 0; }; enum { TYPE_SHAPE, TYPE_POLYGON, }; void CreateObject(int typeID, void** ppObj); ■アプリ実装 main() { IShape* pShape = 0; IRender* pPolygon = 0; CreateObject( TYPE_SHPAE, &pShape); CreateObject( TYPE_POLYGON, &pPolygon); pShape->SetPos(100, 100); pRender->DrawShape( pShape ); delete pRender; delete pShape; } ■engine.dll インターフェースの実装 // engine.dll の実装個所 class CShape : public IShape { public: // interface 実装 bool SetPos( int x, int y ); public: // CShape 公開メソッド bool Draw( HDC hDC ); }; class CPolygon : public IRender { public: // interface 実装 bool DrawShape( IShape* pShape ) { ((CShape*)pShape)->Draw( m_hDC ); } public: // CPolygon 公開メソッド protected: HDC m_hDC; }; ■オブジェクト生成関数 void CreateObject(int typeID, void** ppObj) { switch( type ID) { case TYPE_SHAPE: *ppObj = new CShape; break; case TYPE_POLYGON: *ppObj = new CPolygon; break; } }
その他の回答 (1)
- aris-wiz
- ベストアンサー率38% (96/252)
言語がC++か、C#かC++マネージかなにかわかりませんが、 C++ということで話を進めます。 C++であれば、一番楽なのは、インターフェイスを使用せず、 抽象化クラスを使用して、Drawメソッドをprivateメソッドに指定し Renderクラスを IShapeインターフェイスのフレンドにすれば良いでしょう。 インテリセンスなどからはメソッドが消えないかも知れませんが、 アクセスは制限されるので呼び出そうとすればコンパイルエラーになります。 本来、__interfanceの識別子は動作がコンパイラに依存するものなので あまり、使わない方が良いような気がします。 リファクタリングすれば、 もっとスマートになると思いますが、 質問者さんのコードを変えて C++で書くならこんな感じでしょうか。 //抽象クラス(Interface) class IShape{ public: friend class CRender; virtual void SetPos(int x, int y) = 0; private: virtual void Draw() = 0; }; class CPolygon : public IShape { public: CPolygon(){} ~CPolygon(){} void SetPos(int x, int y){ m_x = x; m_y = y;}; private: void Draw(){ printf( "x:%d y:%d", m_x, m_y ); }; int m_x, m_y; }; class CRender { public: CRender(){} ~CRender(){} bool Draw(IShape*Drawer){ Drawer->Draw(); return true; } }; int main( void ) { // IShape S;//抽象クラスはインスタンス化できないのでエラー IShape *S; //インスタンス化されないのでOK CRender R; S = new CPolygon;//IShapeを実装であるPolygonクラスでインスタンス化する S->SetPos( 100, 200 );//publicなので呼び出しが可能 // S->Draw();//privateのためクラス外からはアクセスできないのでエラー R.Draw(S);//RenderクラスはIShapeとpublicフレンドなので内部で呼び出しが可能 delete S; return 0; } ※全角スペースは半角かタブに変換してください
お礼
早速のご回答ありがとうございます!※ご察し頂いた通り言語はC++になります。 >本来、__interfanceの識別子は動作がコンパイラに依存するものなので クロスプラットフォームも視野に入れていますのでご指摘感謝致します! >Renderクラスを IShapeインターフェイスのフレンドにすれば良いでしょう。 なるほど。勉強になります! また、記載不足で大変申し訳ございませんが、実際にはDrawの引数となるHDCをヘッダーに書きたくないという意図もあります。 // Shapeインターフェイス[公開ヘッダー] class IShape { public: ~IShape(){} virtual bool SetPos(int x, int y) = 0; virtual bool Draw(HDC hDC) = 0; // ★HDCを引数にとります。 }; // 描画インターフェイス[公開ヘッダー] class IRender { public: ~IRender(){} virtual bool DrawShape( IShape* pShape ) = 0; }; // 描画クラス[非公開ヘッダー] #include <windows.h> class CWinRender : public IRender { HDC m_hDC; public: virtual bool DrawShape( IShape* pShape ){ pShape->Draw( m_hDC ); // HDCメンバーを渡す } }; // アプリ #include <IShape.h> #include <IRender.h> Update(IRender* pRender, IShape* pShape ){ pRender->DrawShape( pShape ); } CWinRender以外のコードはHDC(windows.h)をインクルードしていないので、Linuxなどでもビルドできるという意図があります。
お礼
ご回答頂きありがとうございます! >((CShape*)pShape)->Draw( m_hDC ); なるほど!エンジンが生成を担うことで(CreateObjectメソッド)、エンジン内部では生成した型へのキャスト(dynamic_cast)が可能ということですね! これなら呼ばれないメソッドも隠蔽でき、HDC型も知られずに済みそうです。大変貴重なご助言感謝致します。