Initializing a class pointer

Tyro[a.c.edwards] nospam at home.com
Mon Feb 28 03:55:27 PST 2011


On 2/27/2011 10:39 PM, Steven Schveighoffer wrote:
> 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

Thank you all (Steve, Bekenn, and Simen) for your assistance on this.


More information about the Digitalmars-d-learn mailing list