Defining a custom *constructor* (not initializer!)

Steven Schveighoffer schveiguy at yahoo.com
Fri May 11 06:09:18 PDT 2012


On Mon, 07 May 2012 19:00:22 -0400, Mehrdad <wfunction at hotmail.com> wrote:

> On Monday, 7 May 2012 at 21:07:15 UTC, Steven Schveighoffer wrote:
>> I guess I don't really understand that.  Who is responsible for  
>> cleaning up your class instance?  The way I was understanding your  
>> description, I thought it was the C window runtime calling a callback  
>> you provide to it.  Why do you need to have the GC clean it up?
>
>
> Ah, I see why that's confusing.
>
> Here's a (hopefully better) explanation:
>
> Just as with any other object that represents an outside resource (e.g.  
> a File/Stream/whatever), the lifetime of the unmanaged object should  
> always follow the lifetime of the managed object.
>
> In other words, this means that the creation of a Window object MUST be  
> associated with the system call CreateWindow() (which in turns calls the  
> window dispatcher function, WndProc, with the message WM_CREATE).
>
> And, more importantly, this means that if the GC collects the Window  
> object, then DestroyWindow() MUST be called on the kernel object, so  
> that the window handle doesn't get leaked.
>
> Just as with any other resource.
>
>
> The trouble is that, as-is, this behavior is NOT implementable with a  
> simple Window class whose constructor calls CreateWindow() and whose  
> destructor calls DestroyWindow().
>
> Why? Because if you were to do that in the constructor or destructor,  
> the system would call back your WndProc() function, which is a *virtual*  
> function meant to be overridden in the derived classes (so that they can  
> handle events, such as the creation/destruction of the window, or the  
> calculation of the window size, etc. properly).
>
> That would mean your WndProc() in the derived instance would be called  
> *before* the constructor of the derived instance is called, which is  
> obviously not what you want.

OK, I understand what you are saying now.

What about using NVI?

class Window
{
   protected void processMessage_impl(int message) // virtual call
   {}
   final public void processMessage(int message)
   {
     if(message == WM_CREATE)
     {
        // handle specially
     }
     else if(message == WM_DELETE)
     {
        // handle specially
     }
     else
     {
         processMessage_impl(int message);
     }
   }
   private HWND window;
   this()
   {
     window = CreateWindow(&processMessage); // or whatever mechanism, you  
get the idea
   }
   ~this()
   {
     DestroyWindow(window);
   }
}

-Steve


More information about the Digitalmars-d mailing list