Initializing a class pointer

Steven Schveighoffer schveiguy at yahoo.com
Sun Feb 27 05:39:33 PST 2011


On Sat, 26 Feb 2011 19:46:18 -0500, Tyro[a.c.edwards] <nospam at home.com>  
wrote:

> On 2/27/2011 8:52 AM, Simen kjaeraas wrote:
>> Tyro[a.c.edwards] <nospam at home.com> wrote:
>>
>>> I'm trying to convert some c++ code that defines
>>>
>>> T func(par...)
>>> {
>>> Controller * pCtrl = WinGetLong<Controller *> (hwnd);
>>> .
>>> .
>>> .
>>> switch(msg)
>>> {
>>> case FirstMatch:
>>> pCtrl = new Controller (hwnd, reinterpret_cast<CREATESTRUCT *>  
>>> (lParam));
>>> break;
>>> }
>>> }
>>>
>>> I'm not sure why I need a pointer to the class, just trying to figure
>>> it out.
>>
>> Ah. You would not need a pointer to the class in D. Instead, your  
>> function
>> would look something like this:
>>
>> T funct(par...)
>> {
>> auto pCtrl = WinGetLong!Controller(hwnd);
>> ...
>> switch(msg)
>> {
>> case FirstMatch:
>> pCtrl = new Controller(hWnd, cast(CREATESTRUCT*)lParam);
>> break;
>> }
>> }
>>
>> C++ classes are in some ways more akin to D structs, in that:
>>
>> class A {};
>>
>> void foo(){
>> A bar;
>> }
>>
>> bar would be allocated on the stack in C++, while in D bar would be a
>> pointer to a class instance on the heap. (well, it would be null, but
>> when you set it to something, that something would reside on the heap)
>>
>
> Ok, that's essentially what I have, except that I used Controller pCtrl  
> vice auto. WinGetLong however, is a template that calls  
> GetWindowLongPtrA() and casts it's result (in this case) to Controller.  
>   GetWindowLongPtrA() returns LONG_PTR (aka int) and therefore fails  
> miserably on the cast attempt. On the reverse, there is a WinSetLong  
> that attempts to cast Controller to int for use with  
> SetWindowLongPtrA(). Neither of these functions complain when I use  
> Controller* but I end up with the problem of trying to initialize a  
> pointer with a reference to Controller.

You almost certainly do not want a pointer to a class reference.  A class  
typically resides on the heap, but the reference typically does not.   
Therefore, by using a pointer to a class reference, you run very high risk  
of escaping stack data, leading to memory corruption.

Looking at the documentation for GetWindowLongPtr, it appears to get data  
associated with a window.  Likely, this information is the a pointer to  
the Controller class.

I would recommend doing this:

T WinGetLong(T)(HWND hwnd)
{
    return cast(T)cast(void*)GetWindowLongPtrA(hwnd, ...);
}

and

void WinSetLong(T)(HWND hwnd, T t)
{
    SetWindowLongPtrA(hwnd, ..., cast(LONG_PTR)cast(void*)t);
}

where the ... is the index copied from the C++ code (guessing it's  
GWLP_USERDATA?).

btw, reinterpret_cast<T>(x) is equivalent to (T)(void *)x;

-Steve


More information about the Digitalmars-d-learn mailing list