Re: How to use base class & child class as parameter in one function ?
On Friday, 22 May 2020 at 22:44:17 UTC, H. S. Teoh wrote: On Fri, May 22, 2020 at 09:39:16PM +, Vinod K Chandran via Digitalmars-d-learn wrote: [...] So in the same manner, i want void function(Base) = fnPtr wiil work with void function(Child) You cannot, because that's type unsafe: class Base {} class Derived : Base { void derivedFunc() {} } class Another : Base {} void derivedFunc(Derived d) { d.derivedFunc(); } void function(Base) funPtr; funPtr = derivedFunc; // suppose this was allowed Base obj = new Another; funPtr(obj); // crash: obj does not have derivedFunc() T Yeah, I understand that. And i just changed my code. Thanks for the guidance. :)
Re: How to use base class & child class as parameter in one function ?
On Friday, 22 May 2020 at 22:40:50 UTC, Steven Schveighoffer wrote: On 5/22/20 5:39 PM, Vinod K Chandran wrote: [...] That is the opposite of what you are thinking. A function pointer has to be valid based on its parameter types. Covariant functions are allowed. This is OK: void function(Child) fptr; void foo(Base) {} fptr = // OK! it's fine to call fptr with a Child, because it is a Base as well void function(Base) fptr2; void foo2(Child) {} fptr2 = // Error! if you called fptr2 with a Base that is NOT a Child, bad things will happen. This is more clear if you actually try calling them: fptr2(new Base); // the compiler should allow this foo2(new Base); // but would not allow this So why should fptr2 be allowed to point at foo2? -Steve Thank you for the guidance. I got the point. :)
Re: How to use base class & child class as parameter in one function ?
On 5/22/20 5:39 PM, Vinod K Chandran wrote: 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. 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) That is the opposite of what you are thinking. A function pointer has to be valid based on its parameter types. Covariant functions are allowed. This is OK: void function(Child) fptr; void foo(Base) {} fptr = // OK! it's fine to call fptr with a Child, because it is a Base as well void function(Base) fptr2; void foo2(Child) {} fptr2 = // Error! if you called fptr2 with a Base that is NOT a Child, bad things will happen. This is more clear if you actually try calling them: fptr2(new Base); // the compiler should allow this foo2(new Base); // but would not allow this So why should fptr2 be allowed to point at foo2? -Steve
Re: How to use base class & child class as parameter in one function ?
On Fri, May 22, 2020 at 09:39:16PM +, Vinod K Chandran via Digitalmars-d-learn wrote: [...] > So in the same manner, i want > void function(Base) = fnPtr wiil work with > void function(Child) You cannot, because that's type unsafe: class Base {} class Derived : Base { void derivedFunc() {} } class Another : Base {} void derivedFunc(Derived d) { d.derivedFunc(); } void function(Base) funPtr; funPtr = derivedFunc; // suppose this was allowed Base obj = new Another; funPtr(obj); // crash: obj does not have derivedFunc() T -- Век живи - век учись. А дураком помрёшь.
Re: How to use base class & child class as parameter in one function ?
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)
Re: How to use base class & child class as parameter in one function ?
On Fri, May 22, 2020 at 08:55:45PM +, 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
Re: How to use base class & child class as parameter in one function ?
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.
Re: How to use base class & child class as parameter in one function ?
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
Re: How to use base class & child class as parameter in one function ?
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.
Re: How to use base class & child class as parameter in one function ?
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 ?
Re: How to use base class & child class as parameter in one function ?
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); }
Re: How to use base class & child class as parameter in one function ?
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.
Re: How to use base class & child class as parameter in one function ?
if (Child child = cast(Child)parent) { assert(child !is null); }
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 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, ); frm.addHandler(frm.Click, ); 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.