I'm passing a this pointer in my constructor initialization list for use by a base class and VC9 gives me this warning about it...
main.cpp(124) : warning C4355: 'this' : used in base member initializer list
The program runs perfectly as compiled by VC9 Pro or Code::Blocks 10.05. In Code::Blocks 10.05 using MinGW I get no warnings and a perfectly clean compile. I really think its OK but I wanted to run it by the experts here to see what others might think, and naturally, I might be missing something. If there is a problem I'd like to know about it.
Theoretically, the base address of any base class should be the same as the base address of a class from which it singly inherits. That's all I really need to ensure.
The context for what I'm doing is I put together a simple Windows Class Framework. I never use class frameworks myself, as I'm a pure Win32 Sdk coder, but I put one together for myself nonetheless to play with. Here is the code for the whole program. You can try it out and get the warning if you care to. Oh, I did do a search here on this problem first and found this...
http://www.daniweb.com/software-development/cpp/threads/100917
where MattEvans and Ancient Dragon had an exchange over this issue. But it doesn't look like they really resolved it. MattEvans rewrote his program just to get rid of the warning. Here is my code...
#ifndef UNICODE //This program creates a window upon which are displayed
#define UNICODE //continuously updated mouse coordinates, left button
#endif //click positions, window sizing information, and key
#ifndef _UNICODE //presses (concatenated together for simple text display).
#define _UNICODE
#endif
#include <windows.h>
#include <tchar.h>
#include <string>
#ifdef UNICODE
#define String std::wstring
#else
#define String std::string
#endif
#include <cstdio>
struct ProgramData //This object will be used to persist mouse coordinate,
{ //client window dimensions, and left mouse click coordinates
short int xMouse; //across invocations of the Window Procedure so that the
short int yMouse; //data can be displayed on the window during WM_PAINT
short int xSize; //messages. An instance of this object will be allocated
short int ySize; //dynamically in WM_CREATE, and the pointer to it stored
short int xButton; //as instance data in the window's WNDCLASSEX::cbWndExtra
short int yButton; //bytes.
};
class CWinClass //Just a wrapper for registering WNDCLASSEX object
{
public:
CWinClass(WNDPROC fnWndProc, LPCTSTR szClassName, int cbClsExtra, int cbWndExtra, HBRUSH hBackColor, HINSTANCE hInst)
{
wc.lpszClassName = szClassName;
wc.lpfnWndProc = fnWndProc;
wc.style = 0;
wc.cbClsExtra = cbClsExtra;
wc.cbWndExtra = cbWndExtra;
wc.hInstance = hInst;
wc.hIcon = 0;
wc.hIconSm = 0;
wc.hCursor = LoadCursor (0, IDC_ARROW);
wc.hbrBackground = hBackColor;
wc.lpszMenuName = 0;
wc.cbSize = sizeof(WNDCLASSEX);
RegisterClassEx(&wc);
}
private:
WNDCLASSEX wc;
};
class CWindow //CWindow Fully Initialized Constructor
{ //This is a base class
public:
CWindow
(
int iShow,
LPCTSTR szClassName,
LPCTSTR szCaption,
DWORD dwStyle,
int x,
int y,
int iWidth,
int iHeight,
HWND hParent,
HMENU hMenu,
HINSTANCE hIns,
void* lpCreateParams
)
{
this->m_hWnd= //Win Api CreateWindowEx() call
CreateWindowEx
(
0,
szClassName,
szCaption,
dwStyle,
x,
y,
iWidth,
iHeight,
hParent,
(HMENU)hMenu,
hIns,
lpCreateParams
);
this->m_hInst=hIns;
ShowWindow(this->m_hWnd,iShow);
UpdateWindow(this->m_hWnd);
}
WPARAM Run(void) //Wrapper for message pump
{
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
HWND Window(void)
{
return this->m_hWnd;
}
virtual ~CWindow(void) {}
protected:
HINSTANCE m_hInst;
HWND m_hWnd;
};
class CFrame : public CWindow //CFrame : Inherits from CWindow
{
public:
CFrame
(
int iShow,
LPCTSTR szClassName,
LPCTSTR szCaption,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hParent,
HMENU hMenu,
HINSTANCE hIns, //Why is passing 'this' bad as last
void* lpCreateParams //param of initialization list below ... -V-
):CWindow(iShow,szClassName,szCaption,dwStyle,x,y,nWidth,nHeight,hParent,hMenu,hIns,this)
{ //1>.\main.cpp(124) : warning C4355: 'this' : used in base member initializer list
//SetWindowLong(this->m_hWnd,0,(long)this); //Could be done this way and just put
this->m_nCmdShow=iShow; //WM_CREATE code here
}
static long OnCreate(HWND hWnd, LPARAM lParam) //If I pass 'this' into base class
{ //constructor it will be passed into
CREATESTRUCT* pCreateStruct=(CREATESTRUCT*)lParam; //CreateWindowEx() call as a CREATEPARAMS
CFrame* pObj=(CFrame*)pCreateStruct->lpCreateParams; //and be able to be retrieved here in
SetWindowLong(hWnd,0,(long)pObj); //WM_CREATE handler. I'd prefer to do
String* pStr; //it this way, but I could change it. I
pStr=new String; //don't know why VC++ 9 doesn't like it.
SetWindowLong(hWnd,4,(long)pStr);
ProgramData* pPD=(ProgramData*)GlobalAlloc(GPTR,sizeof(ProgramData));
SetWindowLong(hWnd,8,(long)pPD);
return 0L;
}
static long OnSize(HWND hWnd, LPARAM lParam)
{
ProgramData* pPD=(ProgramData*)GetWindowLong(hWnd,8);
pPD->xSize=LOWORD(lParam);
pPD->ySize=HIWORD(lParam);
InvalidateRect(hWnd,NULL,TRUE);
return 0L;
}
static long OnMouseMove(HWND hWnd, LPARAM lParam)
{
ProgramData* pPD=(ProgramData*)GetWindowLong(hWnd,8);
pPD->xMouse=LOWORD(lParam);
pPD->yMouse=HIWORD(lParam);
InvalidateRect(hWnd,NULL,TRUE);
return 0L;
}
static long OnChar(HWND hWnd, WPARAM wParam)
{
String* pStr;
pStr=(String*)GetWindowLong(hWnd,4);
*pStr+=+wParam;
InvalidateRect(hWnd,NULL,FALSE);
return 0;
}
static long OnLButtonDown(HWND hWnd, LPARAM lParam)
{
ProgramData* pPD=(ProgramData*)GetWindowLong(hWnd,8);
pPD->xButton=LOWORD(lParam);
pPD->yButton=HIWORD(lParam);
InvalidateRect(hWnd,NULL,FALSE);
return 0;
}
static long OnPaint(HWND hWnd)
{
PAINTSTRUCT ps;
String s1;
String s2;
String* pStr;
TCHAR szBuffer[16];
HDC hDC;
hDC=BeginPaint(hWnd,&ps);
ProgramData* pPD=(ProgramData*)GetWindowLong(hWnd,8);
s1=_T("xMouse=");
_stprintf(szBuffer,_T("%d"),pPD->xMouse);
s2=szBuffer;
s1+=s2+_T(" yMouse=");
_stprintf(szBuffer,_T("%d"),pPD->yMouse);
s2=szBuffer;
s1+=s2;
TextOut(hDC,0,0,s1.c_str(),s1.length());
if(pPD->xButton||pPD->yButton)
{
s1=_T("xButton=");
_stprintf(szBuffer,_T("%d"),pPD->xButton);
s2=szBuffer;
s1+=s2+_T(" yButton=");
_stprintf(szBuffer,_T("%d"),pPD->yButton);
s2=szBuffer;
s1+=s2;
TextOut
(
hDC,
pPD->xButton+12,
pPD->yButton,
s1.c_str(),
s1.length()
);
pPD->xButton=0, pPD->yButton=0;
}
s1=_T("Width=");
_stprintf(szBuffer,_T("%d"),pPD->xSize);
s2=szBuffer;
s1+=s2+_T(" Height=");
_stprintf(szBuffer,_T("%d"),pPD->ySize);
s2=szBuffer;
s1+=s2;
TextOut(hDC,0,20,s1.c_str(),s1.length());
pStr=(String*)GetWindowLong(hWnd,4);
TextOut(hDC,0,40,pStr->c_str(),pStr->length());
EndPaint(hWnd,&ps);
return 0L;
}
static long OnDestroy(HWND hWnd)
{
String* pStr;
pStr=(String*)GetWindowLong(hWnd,4);
delete pStr;
ProgramData* pPD=(ProgramData*)GetWindowLong(hWnd,8);
GlobalFree(pPD);
PostQuitMessage(0);
return 0L;
}
virtual ~CFrame(void){}
protected:
int m_nCmdShow;
};
LRESULT CALLBACK FrameWndProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
return CFrame::OnCreate(hWnd,lParam);
case WM_SIZE:
return CFrame::OnSize(hWnd,lParam);
case WM_MOUSEMOVE:
return CFrame::OnMouseMove(hWnd,lParam);
case WM_CHAR:
return CFrame::OnChar(hWnd,wParam);
case WM_LBUTTONDOWN:
return CFrame::OnLButtonDown(hWnd,lParam);
case WM_PAINT:
return CFrame::OnPaint(hWnd);
case WM_DESTROY:
return CFrame::OnDestroy(hWnd);
}
return (DefWindowProc(hWnd, msg, wParam, lParam));
}
int WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
CWinClass WinClass(FrameWndProc, _T("Form2"), 0, 12, (HBRUSH)GetStockObject(WHITE_BRUSH), hIns);
CFrame App(iShow,_T("Form2"),_T("Various Inputs"),WS_OVERLAPPEDWINDOW,200,500,295,180,0,(HMENU)0,hIns,0);
return App.Run();
}