2009-08-14 15 views
0

フォワード宣言がうまくいかない(実際には私が意図した通りに動作するかどうかは分かりません)。フォワード宣言の問題

次のように私はcppのファイルを持っている:

int DialogModeless::Create(int dialogID, Presenter* pPresenter) 
{ 
    Ptrs* pPtrs = new Ptrs; 
    pPtrs->pPresenter = pPresenter; 
    pPtrs->pWnd = _derived; 
    HINSTANCE hInstance = ::GetModuleHandle(NULL); 
    _hWnd = ::CreateDialogParam(hInstance, MAKEINTRESOURCE(dialogID), NULL, &Presenter::StatDlgProc, 
     reinterpret_cast<LPARAM>(pPtrs)); 
    return 0; 
} 

私はそれを持っている方法は、プレゼンター:: StatDlgProcは私だけそのアドレスを取っておりますので、この時点で宣言するだけでよいということです。これは、私は、Visual Studio 2008から次のエラーを取得していますように、ケースではないようです。

エラーC2027:未定義の型「プレゼンター」

の使用私はコンパイルするコードをPresenter.hを含める必要が。

誰でもこのことを私に説明できますか?

私はこのような宣言に転送してみました:

class Presenter; 
BOOL CALLBACK Presenter::StatDlgProc(HWND, UINT, WPARAM, LPARAM); 
+0

したがって、 'StatDlgProc'をどのように転送宣言しますか?コードを表示してください。 –

答えて

0

あなたはこのように、クラスだけでなく、(あなたのcppファイル内など)関数を宣言する必要があります:

class Presenter; 

これは、Presenterがクラスであることをコンパイラに伝えるので、それを処理する方法を大まかに知っています。

しかし、(2つのヘッダー間の循環依存性のような)理由がない限り、正しいヘッダーを#含む方が良いでしょう。

+0

まあ、私は、あなたが一般的ではなくこの特定の状況に含めるのが最善のことを言ってほしいと思っています...そして、あなたは私が知っているJason Williamsですか? – Goz

+0

Yep and yep :-) –

5

Presenterのクラス定義なしでは、コンパイラはPresenter::StatDlgProcのアドレスを取る方法をとらない。具体的には、仮想かどうかは分かりません。仮想の場合は、関数呼び出しを参照するコードを生成するために、クラスのvtableのレイアウトを知る必要があります。 (静的な場合、コンパイラはリンク時にアドレスを理論的に解決することができます)。クラス定義がなければ、コンパイラは簡単な関数呼び出しのために命令を出すのか仮想関数の参照を出すのかを決定できません。

+0

グローバルスコープで非クラス関数のアドレスをフォワード・デクレレーションだけで取ることは可能でしょうか? –

+0

のように: 'void func(int parm); funcPtr = &func; 'はい、可能でなければなりません - リンカはそれを解決できます。 – AShelly

0

あなたは前方のいずれかによって、あなたのプレゼンターのクラスを宣言した場合:ジェイソンが提案かそこらのような宣言を作成するによう

class Presenter; 

int DialogModeless::Create(int dialogID, class Presenter* pPresenter); 

が、完全な宣言を含めずに方法はありません仮想、メンバーのいずれのメンバーにもアクセスできます。

これで、簡単にヘッダファイルを構成できます。 modelessdialog.cppはpresenter.hに依存しますが、modelessdialog.hはそうではありませんが、ヘッダーファイル間のやりとりは難しくありません。