Re: MFC and c++ problems
- From: Daniel James <wastebasket@xxxxxxxxxxxxxxxx>
- Date: Sun, 05 Feb 2006 12:01:00 GMT
In article news:<q3mau1ll18dm5msf1i8l6lctath8omii6v@xxxxxxx>, Joseph M.
Newcomer wrote:
But, if a control sends a message to its parent, is it not making the****
assumption that its parent can handle that message? How is this any better
than calling a method defined by the parent?
That is not "making an assumption", that is "defining an interface". The
control says "here is something. Deal with it". It doesn't care if the
parent deals with it or not. This is quite different than knowing the
parent has a CString variable that is going to reflect something important.
****
That depends. We don't know why the OP wanted a control to communicate with
the parent ... it could be that the control, in this case, DOES care whether
the parent deals with it or not. You'll probably say that's bad design -- *I*
say that's bad design -- but the devil's advocate doesn't care.
I agree that if what we're looking at is just a notification the control
doesn't care.
Semantically, of course, the parent is free not to handle any message that****
it doesn't understand. Your program containing a control that sends
messages to its parent will compile and run ... but may not WORK, because
the control may require the parent to handle the messages it sends, and
make some response.
Sure. And the point is? Key here is that it doesn't care HOW the parent
handles it, and if the parent fails to handle it, that is a problem with
the parent. If the consequence of this is that the program doesn't work,
that isn't the problem of the control. It has discharged its entire
responsibility when it sends the message to the parent. And that's
a key idea in thinking about how to design controls.
*****
Right: if the control defines an interface in terms of message passing and the
parent that owns the control doesn't use that interface correctly the program
won't work ... and you're saying that that's the owner's problem not the
control's. You are right ... but the goal here is to try to see whether we can
avoid the situation altogether and try to ensure that the control and its
owner *do* use the same interface.
The POINT -- and remember that I made this point with my devil's advocate's
hat on -- that you don't get any compile-time indication of an incompatibility
between the way the control and its owner understand that interface. With
method calls you get a compile error. This surely is a Good Thing (TM).
If MyControl calls methods in its parent directly there is a visible****
connection between control and parent that documents the real-world
connection between their behaviours. If you place that control in a parent
that doesn't provide the methods that the control needs to call your
program will fail to compile ... which is rather better, in my book, than
having it compile and run but not work.
But how can it? To do this, it has to know the name of the parent, the
methods in the parent, etc.
Let's say we have a control called MyFancyWidget and a dialog class that wants
to use one (or more) of these controls. We place a reuqirement that the dialog
must inherit from an abstract class MyFancyWidgetUser. MyFancyWidgetUser
defines one or more functions -- let's say it defines a function called
DoParentFoo -- which the dialog must implement if it is to contain
MyFancyWidget controls (otherwise it will be an incomplete class and the code
won't compile). When the dialog creates the control it passes a pointer to
itself as a MyFancyWidgetUser:
MyFancyWidget::MyFancyWidget( MyFancyWidgetUser *parent, ... );
....
m_ctlExample = new MyFancyWidget( this, ... );
The control stores that pointer in a const member (say m_pMyParent) so it can
use it later. If the dialog doesn't inherit from MyFancyWidgetUser the
implicit conversion of the constructor argument will fail to compile.
When a control in the running application wants to Foo its parent (whatever
that may mean) it can call m_pMyParent->DoParentFoo() (probably passing the
control ID or a pointer to itself so that the parent can tell which of a
number of MyFancyWidget children called it).
To do this the control only has to know that its parent is a MyFancyWidgetUser
and what facilities (methods) the MyFancyWidgetUser interface exposes -- these
are, of course, part of the interface we have defined for MyFancyWidget.
This makes it completely non-reusable.
It's reusable by any dialog (or view, etc) that inherits from the abstract
MyFancyWidgetUser class.
If you change the nature of the parent, even within your own project, you
can make such controls no longer compilable.
Not as long as you keep that interface definition fixed.
That's the benefit of encapsulating the interface definition in a class of its
own.
Except for all the other problems of multiple inheritance ...
Those problems essentially vanish when the interface class has no data
members. What I'm suggesting here is a pure abstract class, so it doesn't even
contain implementations of the methods it defines. It's pure syntactic sugar.
I agree that SendMessage has type safety problems. This is a real downside
of using it.
That's really the point that I was making in my self-appointed role as devil's
advocate.
SendMessage seems very clearly the right approach for notifications. For other
reasons that one might want communication between a contol and its parent the
position isn't entirely cut and dry, though, and issues like type safety do
suggest other approaches. Those other approaches *can* be implemented without
sacrificing reusability, which you seemed to be suggesting they couldn't.
To be honest, though, (and discarding my devil's advocate costume) I can't
think of any good reason, offhand, for a control to communicate with its
parent for any reason other than to notify it of some change. I'd need
convincing that a design that had other requirements was well-conceived.
Cheers,
Daniel.
.
- References:
- MFC and c++ problems
- From: Benry
- Re: MFC and c++ problems
- From: Joseph M . Newcomer
- Re: MFC and c++ problems
- From: Ajay Kalra
- Re: MFC and c++ problems
- From: Joseph M . Newcomer
- Re: MFC and c++ problems
- From: Daniel James
- Re: MFC and c++ problems
- From: Joseph M . Newcomer
- MFC and c++ problems
- Prev by Date: Re: Should I use Winforms ?
- Next by Date: Re: MFC and c++ problems
- Previous by thread: Re: MFC and c++ problems
- Next by thread: Re: MFC and c++ problems
- Index(es):
Relevant Pages
|