views:

152

answers:

3

I'm having a problem getting forward declaration to work (actually I'm not sure if it should work the way I intend).

I have a cpp file as follows:

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;
}

Now the way I have it is that Presenter::StatDlgProc need only be declared at this point since I am only taking its address. This does not seem to be the case as I am getting the following error from Visual Studio 2008:

error C2027: use of undefined type 'Presenter'

I have to include Presenter.h for the code to compile.

Can anyone explain this to me?

I tried to forward declare like this:

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

You'll need to declare the class as well as the function (e.g. in your cpp file), like this:

class Presenter;

This tells the compiler that Presenter is a class, so it knows roughly how to deal with it.

But unless you have a good reason (like a circular dependency between two headers), it's better to #include the proper header.

Jason Williams
Well I do hope you are saying its best to include in this specific circumstance rather than in general ... and, btw, are you the Jason Williams I know?
Goz
Yep and yep :-)
Jason Williams
+5  A: 

without the class definition of Presenter, the compiler does not how to take the address of Presenter::StatDlgProc. Specifically, it doesn't know if it is virtual or not. If it is virtual, it needs to know the layout of the class's vtable in order to generate the code which will look up the function call. (If it is static, the compiler could theoretically resolve the address at link time.) So without the class definition, the compliler can't decide whether to emit instructions for a simple function call or for a virtual function lookup.

AShelly
Would it be possible to take the address of a non-class function at global scope with only a forward decleration?
like: `void func(int parm); funcPtr = ` Yes, it should be possible - the linker can resolve that one.
AShelly
A: 

If you forward declare your presenter class either by:

class Presenter;

as Jason suggested or in the create declaration like so:

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

but without including a full declaration there is no way to access any member whether it be static, virtual or member.

Now you can structure the header files easily. Although modelessdialog.cpp depends on presenter.h but modelessdialog.h does not so there is no difficult interaction between the header files.

Elemental