digitalmars.D.learn - How to use base class & child class as parameter in one function ?
- Vinod K Chandran (59/59) May 22 2020 Hi all,
- rikki cattermole (3/3) May 22 2020 if (Child child = cast(Child)parent) {
- Vinod K Chandran (3/6) May 22 2020 Actually, problem occurs in addHandler function. It expects an
- Steven Schveighoffer (18/25) May 22 2020 Yes, because what if you did this with your function:
- Vinod K Chandran (17/45) May 22 2020 Thanks for the answer. I understand that, in D, derived class and
- Adam D. Ruppe (2/4) May 22 2020 Direct translation of this code works just fine in D.
- Vinod K Chandran (9/13) May 22 2020 Yeah, my bad. I just checked in D. But think inherited type
- H. S. Teoh (29/41) May 22 2020 [...]
- Steven Schveighoffer (7/57) May 22 2020 Yes. What you cannot do is this (which I hope doesn't compile in VB.net,...
- Vinod K Chandran (7/15) May 22 2020 Nope--
- Steven Schveighoffer (17/35) May 22 2020 That is the opposite of what you are thinking. A function pointer has to...
- Vinod K Chandran (3/22) May 23 2020 Thank you for the guidance. I got the point. :)
- H. S. Teoh (16/19) May 22 2020 You cannot, because that's type unsafe:
- Vinod K Chandran (3/20) May 23 2020 Yeah, I understand that. And i just changed my code. Thanks for
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 22 2020
if (Child child = cast(Child)parent) { assert(child !is null); }
May 22 2020
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
On 5/22/20 9:10 AM, Vinod K Chandran wrote:On Friday, 22 May 2020 at 12:21:25 UTC, rikki cattermole wrote: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); }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
On Friday, 22 May 2020 at 16:12:12 UTC, Steven Schveighoffer wrote:On 5/22/20 9:10 AM, Vinod K Chandran wrote: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 ?On Friday, 22 May 2020 at 12:21:25 UTC, rikki cattermole wrote: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); }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
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
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: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.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
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:[...] 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 SmoorenburgOn Friday, 22 May 2020 at 20:04:24 UTC, Vinod K Chandran wrote: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.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
On 5/22/20 4:04 PM, Vinod K Chandran wrote:On Friday, 22 May 2020 at 16:12:12 UTC, Steven Schveighoffer 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. -SteveOn 5/22/20 9:10 AM, Vinod K Chandran wrote: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 ?On Friday, 22 May 2020 at 12:21:25 UTC, rikki cattermole wrote: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); }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
On Friday, 22 May 2020 at 20:51:20 UTC, Steven Schveighoffer wrote:On 5/22/20 4:04 PM, Vinod K Chandran wrote: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)[...]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
On 5/22/20 5:39 PM, Vinod K Chandran wrote:On Friday, 22 May 2020 at 20:51:20 UTC, Steven Schveighoffer 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 = &foo; // 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 = &foo2; // 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? -SteveOn 5/22/20 4:04 PM, Vinod K Chandran wrote: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)[...]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.
May 22 2020
On Friday, 22 May 2020 at 22:40:50 UTC, Steven Schveighoffer wrote:On 5/22/20 5:39 PM, Vinod K Chandran wrote:Thank you for the guidance. I got the point. :)[...]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 = &foo; // 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 = &foo2; // 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
May 23 2020
On Fri, May 22, 2020 at 09:39:16PM +0000, 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 -- Век живи - век учись. А дураком помрёшь.
May 22 2020
On Friday, 22 May 2020 at 22:44:17 UTC, H. S. Teoh wrote:On Fri, May 22, 2020 at 09:39:16PM +0000, Vinod K Chandran via Digitalmars-d-learn wrote: [...]Yeah, I understand that. And i just changed my code. Thanks for the guidance. :)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
May 23 2020