Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
May 22, 2020 How to use base class & child class as parameter in one function ? | ||||
---|---|---|---|---|
| ||||
Hi all, I have a windows gui setup like this; class EventArgs {} \\ Base class for all messages class MouseEventArgs : EventArgs { // child class for handling mouse messages ... int x; int y; this(WPARAM wpm, LPARAM lpm){ this.x = xFromLparam(lpm); this.y = yFromLparam(lpm); } } alias EvtFuncPtr = void function(EventArgs); // function pointer struct MsgHandler { uint message ; HWND handle ; bool isActive ; EvtFuncPtr fnPtr; } // Then in my window class... void addHandler(uint we, EvtFuncPtr fnp){ // This is error point. auto mh = MsgHandler(); mh.handle = this.mHandle; mh.message = we; mh.fnPtr = fnp; mh.isActive = true; this.msgHandlerList ~= mh; // This is a list<MsgHandler> in window class. } // And in the WndProc... auto thisWin = findWindowClass(hWnd); // get the window class with hWnd. auto mh = thisWin.findHandler(hWnd, message); // get the event handler for this message & hWnd if(mh.isActive) { // if there is an event handler fixed, switch (message){ case 512 : .. case 526 : // if it's a Mouse messages auto ea = new MouseEventArgs(wParam, lParam); mh.fnPtr(ea); // execute that event handler function break; default : break; } } // And this is the window creation site... auto app = new Application() ; auto frm = new Window(app) ; frm.createWindow() ; frm.addHandler(frm.load, &onLoad); frm.addHandler(frm.Click, &onClick); void onLoad(EventArgs e){ log("form is loaded..."); } void onClick(MouseEventArgs e){ // Compiler wants to change the MouseEventArgs with EventArgs. log("form clicked on x = ", e.x, ", and y = ", e.y); } I wrote EventArgs as the parameter type in function pointer but i want to use it's child classes also. But i can't. |
May 23, 2020 Re: How to use base class & child class as parameter in one function ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vinod K Chandran | if (Child child = cast(Child)parent) { assert(child !is null); } |
May 22, 2020 Re: How to use base class & child class as parameter in one function ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to rikki cattermole | On Friday, 22 May 2020 at 12:21:25 UTC, rikki cattermole wrote:
> if (Child child = cast(Child)parent) {
> assert(child !is null);
> }
Actually, problem occurs in addHandler function. It expects an argument of type "EventArgs", not MouseEventArgs.
|
May 22, 2020 Re: How to use base class & child class as parameter in one function ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vinod K Chandran | On 5/22/20 9:10 AM, Vinod K Chandran wrote:
> On Friday, 22 May 2020 at 12:21:25 UTC, rikki cattermole wrote:
>> if (Child child = cast(Child)parent) {
>> assert(child !is null);
>> }
>
> Actually, problem occurs in addHandler function. It expects an argument of type "EventArgs", not MouseEventArgs.
Yes, because what if you did this with your function:
fnp(new EventArgs(...));
It would be called with the type being implicitly cast to the child type without that being true.
What Rikki was recommending is that you write your handler like this:
void onClick(EventArgs e){
if(auto me = cast(MouseEventArgs)e) {
log("form clicked on x = ", me.x, ", and y = ", me.y);
}
}
Actually, if you are certain it's a programming error for onClick to be called with a different type of event args, I'd do:
void onClick(EventArgs e){
auto me = cast(MouseEventArgs)e;
assert(me !is null, "Error, onClick called with invalid event type");
log("form clicked on x = ", me.x, ", and y = ", me.y);
}
|
May 22, 2020 Re: How to use base class & child class as parameter in one function ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Friday, 22 May 2020 at 16:12:12 UTC, Steven Schveighoffer wrote:
> On 5/22/20 9:10 AM, Vinod K Chandran wrote:
>> On Friday, 22 May 2020 at 12:21:25 UTC, rikki cattermole wrote:
>>> if (Child child = cast(Child)parent) {
>>> assert(child !is null);
>>> }
>>
>> Actually, problem occurs in addHandler function. It expects an argument of type "EventArgs", not MouseEventArgs.
>
> Yes, because what if you did this with your function:
>
> fnp(new EventArgs(...));
>
> It would be called with the type being implicitly cast to the child type without that being true.
>
> What Rikki was recommending is that you write your handler like this:
>
> void onClick(EventArgs e){
> if(auto me = cast(MouseEventArgs)e) {
> log("form clicked on x = ", me.x, ", and y = ", me.y);
> }
> }
>
> Actually, if you are certain it's a programming error for onClick to be called with a different type of event args, I'd do:
>
> void onClick(EventArgs e){
> auto me = cast(MouseEventArgs)e;
> assert(me !is null, "Error, onClick called with invalid event type");
> log("form clicked on x = ", me.x, ", and y = ", me.y);
> }
Thanks for the answer. I understand that, in D, derived class and base class are not the same as in vb.net or any other language. (Please correct me if i am wrong).
In vb.net, assume that i have a class setup like this--
Public Class Base
Public Property SampleInt As Integer
End Class
Public Class Child : Inherits Base
Public Property SampleDouble As Double
End Class
//Assume that i have a list of Base class like this--
Dim sampleList As New List(Of Base)
// Now, i can use this list like this--
sampleList.Add(New Child(10.5)) Is this possible in D without casting ?
|
May 22, 2020 Re: How to use base class & child class as parameter in one function ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vinod K Chandran | On Friday, 22 May 2020 at 20:04:24 UTC, Vinod K Chandran wrote:
> sampleList.Add(New Child(10.5)) Is this possible in D without casting ?
Direct translation of this code works just fine in D.
|
May 22, 2020 Re: How to use base class & child class as parameter in one function ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vinod K Chandran | On 5/22/20 4:04 PM, Vinod K Chandran wrote:
> On Friday, 22 May 2020 at 16:12:12 UTC, Steven Schveighoffer wrote:
>> On 5/22/20 9:10 AM, Vinod K Chandran wrote:
>>> On Friday, 22 May 2020 at 12:21:25 UTC, rikki cattermole wrote:
>>>> if (Child child = cast(Child)parent) {
>>>> assert(child !is null);
>>>> }
>>>
>>> Actually, problem occurs in addHandler function. It expects an argument of type "EventArgs", not MouseEventArgs.
>>
>> Yes, because what if you did this with your function:
>>
>> fnp(new EventArgs(...));
>>
>> It would be called with the type being implicitly cast to the child type without that being true.
>>
>> What Rikki was recommending is that you write your handler like this:
>>
>> void onClick(EventArgs e){
>> if(auto me = cast(MouseEventArgs)e) {
>> log("form clicked on x = ", me.x, ", and y = ", me.y);
>> }
>> }
>>
>> Actually, if you are certain it's a programming error for onClick to be called with a different type of event args, I'd do:
>>
>> void onClick(EventArgs e){
>> auto me = cast(MouseEventArgs)e;
>> assert(me !is null, "Error, onClick called with invalid event type");
>> log("form clicked on x = ", me.x, ", and y = ", me.y);
>> }
>
> Thanks for the answer. I understand that, in D, derived class and base class are not the same as in vb.net or any other language. (Please correct me if i am wrong).
> In vb.net, assume that i have a class setup like this--
> Public Class Base
> Public Property SampleInt As Integer
> End Class
>
> Public Class Child : Inherits Base
> Public Property SampleDouble As Double
> End Class
> //Assume that i have a list of Base class like this--
> Dim sampleList As New List(Of Base)
> // Now, i can use this list like this--
> sampleList.Add(New Child(10.5)) Is this possible in D without casting ?
>
Yes. What you cannot do is this (which I hope doesn't compile in VB.net, but I wouldn't be surprised):
Dim sampleList As New List(Of Child)
sampleList.Add(New Base(10))
Which is the equivalent of what you were requesting.
-Steve
|
May 22, 2020 Re: How to use base class & child class as parameter in one function ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On Friday, 22 May 2020 at 20:06:20 UTC, Adam D. Ruppe wrote:
> On Friday, 22 May 2020 at 20:04:24 UTC, Vinod K Chandran wrote:
>> sampleList.Add(New Child(10.5)) Is this possible in D without casting ?
>
> Direct translation of this code works just fine in D.
Yeah, my bad. I just checked in D. But think inherited type difference is a problem in function pointer's parameters only.
alias EvtFuncPtr = void function(EventArgs);
Now, this EvtFuncPtr won't allow any derived classes of EventArgs as parameter. That's the problem i am facing. What about a template ?
alias EvtFuncPtr = void function(T)(T = EventArgs);
This is not compiled.
|
May 22, 2020 Re: How to use base class & child class as parameter in one function ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vinod K Chandran | On Fri, May 22, 2020 at 08:55:45PM +0000, Vinod K Chandran via Digitalmars-d-learn wrote: > On Friday, 22 May 2020 at 20:06:20 UTC, Adam D. Ruppe wrote: > > On Friday, 22 May 2020 at 20:04:24 UTC, Vinod K Chandran wrote: > > > sampleList.Add(New Child(10.5)) Is this possible in D without > > > casting ? > > > > Direct translation of this code works just fine in D. > > Yeah, my bad. I just checked in D. But think inherited type difference > is a problem in function pointer's parameters only. > alias EvtFuncPtr = void function(EventArgs); > Now, this EvtFuncPtr won't allow any derived classes of EventArgs as > parameter. That's the problem i am facing. [...] So you're basically saying: void function(DerivedClass) cannot implicitly convert to: void function(BaseClass) right? This is as it should be: class Base { ... } class Derived : Base { ... } class Another : Base { ... } void baseFunc(Base) { ... } void derivedFunc(Derived) { ... } void function(Base) funcPtr; funcPtr = baseFunc; // OK funcPtr = derivedFunc; // Not allowed Why is it bad to assign derivedFunc to funcPtr? Consider this: Base obj = new Another; funcPtr = baseFunc; funcPtr(obj); // OK, because Another is a subtype of Base funcPtr = derivedFunc; // suppose this was allowed funcPtr(obj); // Uh oh, derivedFunc receives an argument of // type Another which is not a subtype of // Derived So, it's not permissible to allow assigning derivedFunc to funcPtr without a cast. T -- Indifference will certainly be the downfall of mankind, but who cares? -- Miquel van Smoorenburg |
May 22, 2020 Re: How to use base class & child class as parameter in one function ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Friday, 22 May 2020 at 20:51:20 UTC, Steven Schveighoffer wrote:
> On 5/22/20 4:04 PM, Vinod K Chandran wrote:
>> [...]
>
> Yes. What you cannot do is this (which I hope doesn't compile in VB.net, but I wouldn't be surprised):
>
> Dim sampleList As New List(Of Child)
> sampleList.Add(New Base(10))
>
> Which is the equivalent of what you were requesting.
>
> -Steve
Nope--
List(Of Base) will contain an instance of a Child.
So in the same manner, i want
void function(Base) = fnPtr wiil work with
void function(Child)
|
Copyright © 1999-2021 by the D Language Foundation