<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Falscher Aufruf von virtueller Methode]]></title><description><![CDATA[<p>Ich habe ein ganz merkwuerdiges Problem. Ich versuche gerade mir eine kleine GUI-Toolbox zu schreiben. Bei der Objektirisierung der WinAPI gibt es das Problem, dass man eine klassische C-Funktion als Callback braucht welche von Windows ein Handle uebergeben kriegt. Das Problem habe ich mit einem assoziativen Map und einer statischen Methode geloest. Beim Erzeugen meiner Fensterobjekte wird das Handle mit dem this-pointer des Objektes assoziiert. Ueber den Map kann die statische Methode, welche als Callback uebergeben wurde, dann auf die Daten des dazugehoerigen Objektes zugreifen.<br />
Logischerweise moeche ich von dieser Klasse ableiten und die einzelnen Methoden, z.B. Malen, ueberladen. Das funktioniert aber irgendwie nicht.<br />
Hier ersteinmal der Code:</p>
<pre><code class="language-cpp">#include	&lt; windows.h &gt;
#include	&lt; commctrl.h &gt;
#include	&lt; map &gt;

class Widget
{
public:
           Widget  ( );
  virtual  ~Widget ( )  { }
protected:

  virtual void  paint ()
  {
/* &lt;-- wenn ich den Kommentar entferne wird dieser Code hier ausgefuert anstelle der ueberladenen Methode !!!!!!!!!!!!!!!!!!!!!
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint ( winHandle , &amp;ps );
    TextOut  ( hdc, 10, 10, &quot;Parent&quot;, 6 );
    EndPaint ( winHandle , &amp;ps );
*/
  }

  HWND		winHandle;

private:
  int		argNum;
  char*		winName;
  HINSTANCE	instanceHandle;
  WNDCLASS	winClass;

  static LRESULT CALLBACK  WinProc ( HWND hWin, UINT message, WPARAM wParam, LPARAM lParam );
  static std::map&lt; HWND , Widget* &gt;   mapWin;
};

std::map&lt; HWND , Widget* &gt;  Widget::mapWin;

Widget::Widget () :
  winName ( &quot;winName&quot; ),
  argNum  ( 1 )
{
  instanceHandle = GetModuleHandle(0);

  winClass.lpszClassName   = winName;
  winClass.lpfnWndProc     = WinProc;
  winClass.cbClsExtra      = 0;
  winClass.cbWndExtra      = 0;
  winClass.hbrBackground   = (HBRUSH) GetStockObject( WHITE_BRUSH );
  winClass.hCursor         = LoadCursor( NULL, IDC_ARROW );
  winClass.hIcon           = LoadIcon( NULL, IDI_APPLICATION );
  winClass.hInstance       = instanceHandle;
  winClass.lpszMenuName    = NULL;
  winClass.style           = CS_HREDRAW | CS_VREDRAW;

  RegisterClass( &amp;winClass );

  winHandle = CreateWindow( winName, winName,
                            WS_SYSMENU | WS_MINIMIZEBOX |
                            WS_MAXIMIZEBOX | WS_THICKFRAME,
                            10,180,700,500,
                            NULL, NULL, instanceHandle, NULL);

//// associate the created Widget with this object
  mapWin[winHandle] = this;

  ShowWindow ( winHandle , argNum );
  UpdateWindow ( winHandle );
}

LRESULT CALLBACK  Widget::WinProc ( HWND hWin, UINT message, WPARAM wParam, LPARAM lParam )
{
  switch (message)
  {
    case WM_PAINT:     mapWin[hWin]-&gt;paint();   return 0;
    case WM_DESTROY:   PostQuitMessage(0);      return 0;
  }

  return DefWindowProc(hWin, message, wParam, lParam);
}

//// child mit ueberladener paint()-methode ////////////////////////////////////

class FensterMitWasDrin : public Widget
{
  void  paint()
  {
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint ( winHandle , &amp;ps );
    TextOut ( hdc, 10, 10, &quot;Child&quot;, 5 );
    EndPaint ( winHandle , &amp;ps );
  }
};

//// Hauptprogramm /////////////////////////////////////////////////////////////

int WINAPI   WinMain  (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR arg, int argNr)
{
  MSG  msg;

  FensterMitWasDrin  MainWidget;

  while ( GetMessage(&amp;msg, NULL, 0, 0) )
  {
    TranslateMessage(&amp;msg);
    DispatchMessage(&amp;msg);
  }

  return  msg.wParam;
}
</code></pre>
<p>Das ganze funktioniert nur solange ich nichts in die paint()-methode des Parent schreibe. Sobald ich den oben markierten Code aus dem Kommentar nehme, wird statt der paint()-Methode des Childs die des Parent ausgefuehrt.<br />
Habe ich irgendetwas nicht beachtet?<br />
Ich hoffe mir kann da jemand helfen.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/192167/falscher-aufruf-von-virtueller-methode</link><generator>RSS for Node</generator><lastBuildDate>Sun, 27 Sep 2026 07:59:09 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/192167.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 11 Sep 2007 12:02:43 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Falscher Aufruf von virtueller Methode on Tue, 11 Sep 2007 12:02:43 GMT]]></title><description><![CDATA[<p>Ich habe ein ganz merkwuerdiges Problem. Ich versuche gerade mir eine kleine GUI-Toolbox zu schreiben. Bei der Objektirisierung der WinAPI gibt es das Problem, dass man eine klassische C-Funktion als Callback braucht welche von Windows ein Handle uebergeben kriegt. Das Problem habe ich mit einem assoziativen Map und einer statischen Methode geloest. Beim Erzeugen meiner Fensterobjekte wird das Handle mit dem this-pointer des Objektes assoziiert. Ueber den Map kann die statische Methode, welche als Callback uebergeben wurde, dann auf die Daten des dazugehoerigen Objektes zugreifen.<br />
Logischerweise moeche ich von dieser Klasse ableiten und die einzelnen Methoden, z.B. Malen, ueberladen. Das funktioniert aber irgendwie nicht.<br />
Hier ersteinmal der Code:</p>
<pre><code class="language-cpp">#include	&lt; windows.h &gt;
#include	&lt; commctrl.h &gt;
#include	&lt; map &gt;

class Widget
{
public:
           Widget  ( );
  virtual  ~Widget ( )  { }
protected:

  virtual void  paint ()
  {
/* &lt;-- wenn ich den Kommentar entferne wird dieser Code hier ausgefuert anstelle der ueberladenen Methode !!!!!!!!!!!!!!!!!!!!!
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint ( winHandle , &amp;ps );
    TextOut  ( hdc, 10, 10, &quot;Parent&quot;, 6 );
    EndPaint ( winHandle , &amp;ps );
*/
  }

  HWND		winHandle;

private:
  int		argNum;
  char*		winName;
  HINSTANCE	instanceHandle;
  WNDCLASS	winClass;

  static LRESULT CALLBACK  WinProc ( HWND hWin, UINT message, WPARAM wParam, LPARAM lParam );
  static std::map&lt; HWND , Widget* &gt;   mapWin;
};

std::map&lt; HWND , Widget* &gt;  Widget::mapWin;

Widget::Widget () :
  winName ( &quot;winName&quot; ),
  argNum  ( 1 )
{
  instanceHandle = GetModuleHandle(0);

  winClass.lpszClassName   = winName;
  winClass.lpfnWndProc     = WinProc;
  winClass.cbClsExtra      = 0;
  winClass.cbWndExtra      = 0;
  winClass.hbrBackground   = (HBRUSH) GetStockObject( WHITE_BRUSH );
  winClass.hCursor         = LoadCursor( NULL, IDC_ARROW );
  winClass.hIcon           = LoadIcon( NULL, IDI_APPLICATION );
  winClass.hInstance       = instanceHandle;
  winClass.lpszMenuName    = NULL;
  winClass.style           = CS_HREDRAW | CS_VREDRAW;

  RegisterClass( &amp;winClass );

  winHandle = CreateWindow( winName, winName,
                            WS_SYSMENU | WS_MINIMIZEBOX |
                            WS_MAXIMIZEBOX | WS_THICKFRAME,
                            10,180,700,500,
                            NULL, NULL, instanceHandle, NULL);

//// associate the created Widget with this object
  mapWin[winHandle] = this;

  ShowWindow ( winHandle , argNum );
  UpdateWindow ( winHandle );
}

LRESULT CALLBACK  Widget::WinProc ( HWND hWin, UINT message, WPARAM wParam, LPARAM lParam )
{
  switch (message)
  {
    case WM_PAINT:     mapWin[hWin]-&gt;paint();   return 0;
    case WM_DESTROY:   PostQuitMessage(0);      return 0;
  }

  return DefWindowProc(hWin, message, wParam, lParam);
}

//// child mit ueberladener paint()-methode ////////////////////////////////////

class FensterMitWasDrin : public Widget
{
  void  paint()
  {
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint ( winHandle , &amp;ps );
    TextOut ( hdc, 10, 10, &quot;Child&quot;, 5 );
    EndPaint ( winHandle , &amp;ps );
  }
};

//// Hauptprogramm /////////////////////////////////////////////////////////////

int WINAPI   WinMain  (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR arg, int argNr)
{
  MSG  msg;

  FensterMitWasDrin  MainWidget;

  while ( GetMessage(&amp;msg, NULL, 0, 0) )
  {
    TranslateMessage(&amp;msg);
    DispatchMessage(&amp;msg);
  }

  return  msg.wParam;
}
</code></pre>
<p>Das ganze funktioniert nur solange ich nichts in die paint()-methode des Parent schreibe. Sobald ich den oben markierten Code aus dem Kommentar nehme, wird statt der paint()-Methode des Childs die des Parent ausgefuehrt.<br />
Habe ich irgendetwas nicht beachtet?<br />
Ich hoffe mir kann da jemand helfen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1363232</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1363232</guid><dc:creator><![CDATA[katana. 0]]></dc:creator><pubDate>Tue, 11 Sep 2007 12:02:43 GMT</pubDate></item><item><title><![CDATA[Reply to Falscher Aufruf von virtueller Methode on Tue, 11 Sep 2007 12:23:58 GMT]]></title><description><![CDATA[<p>katana. schrieb:</p>
<blockquote>
<p>...</p>
<pre><code class="language-cpp">...
Widget::Widget () ...
{
...
  mapWin[winHandle] = this;
...
</code></pre>
</blockquote>
<p>Ich vermute, dass das daran liegt, dass Du ja hier einen Zeiger auf das &quot;Widget-Subobjekt&quot; in die Map legst.<br />
... neee, daran liegt's doch nicht. Bei mir (MinitestPG) klappt das jedenfalls wie gewünscht.</p>
<p>EDIT2: Ein wenig überrascht mich aber, dass paint() bei Deinem &quot;FensterMitWasDrin&quot; private ist - oder nur ein typo ?</p>
<p>Gruß,</p>
<p>Simon2.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1363244</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1363244</guid><dc:creator><![CDATA[Simon2]]></dc:creator><pubDate>Tue, 11 Sep 2007 12:23:58 GMT</pubDate></item></channel></rss>