dポイントプレゼントキャンペーン実施中!

__interfaceに定義するメソッドについて教えてください!

描画エンジン(engine.dll)を作成しているのですが、アプリ(App.exe)からは呼んで欲しくないメソッドをインターフェイスに定義する必要があり困っています。具体的には、以下のDrawメソッドになります。

// 形状インターフェイス[engine.dll]
__interface IShape {
bool Draw(); // ★CRenderクラスから呼ばれる
bool SetPos( int x, int y );
};

// 描画クラス[engine.dll]
class CRender {
bool DrawShape( IShape* pShape ); // pShape->Draw();をする
};

// アプリ[App.exe]
CRender* pRender = new CRender();
IShape* pShape = new CPolygon();
pShape->SetPos(100, 100);
pRender->DrawShape( pShape );

DrawメソッドはCRenderが呼ぶメソッドなので、アプリには公開しなくてもよいメソッドになっています。公開する必要がないので、隠蔽するのが正しいと思っていますが、良い案がございましたらご助言ください。

「__interfaceに定義するメソッド」の質問画像

A 回答 (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;
}
}
    • good
    • 0
この回答へのお礼

ご回答頂きありがとうございます!

>((CShape*)pShape)->Draw( m_hDC );
なるほど!エンジンが生成を担うことで(CreateObjectメソッド)、エンジン内部では生成した型へのキャスト(dynamic_cast)が可能ということですね!

これなら呼ばれないメソッドも隠蔽でき、HDC型も知られずに済みそうです。大変貴重なご助言感謝致します。

お礼日時:2010/11/03 09:47

言語が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;
}

※全角スペースは半角かタブに変換してください
    • good
    • 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などでもビルドできるという意図があります。

お礼日時:2010/11/02 20:30

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!