Re: dynamic_cast is ugly!
On Mar 11, 1:10 pm, "Daniel T." <danie...@earthlink.net> wrote:
On Mar 10, 4:40 pm, "andrew queisser" <andrew.queis...@hp.com> wrote:
"Ian Collins" <ian-n...@hotmail.com> wrote in message
Add no-op defaults to the parent class!
This requires you know what extensions derived classes
will add and what types they will use, or have access to
the base to add the no-ops.
I'll hazard a guess: Phlip was just trying to throw me a
bone by asking for something everybody is already objecting
I'm not so sure I would categorically object to no-op
I don't think anyone would, although it always depends.
They are a valid design choice in some situations IMO. Valid
in more situations than down casting for sure.
The problem is encapsulation. The base class shouldn't
necessarily know about what additional interfaces the derived
class may decide to add. (Sometimes, it's appropriate that it
know it, and other times, it isn't.)
To Ian's comment, adding no-op defaults requires only that the
base class interface be designed for the contexts it is used
in. Which of course, has to be done in any case.
I think you're missing the point. The base class interface is
only designed for a specific use. Some derived classes may want
to define additional functionality. The reason the client code
uses a dynamic_cast is precisely because the base class wasn't
designed to be used in the given context.
Consider a concrete example. Objects are identified by DN's.
You certainly don't want all of the functionality of every
possible object declared down in the basic object type
manipulated by the directory services. All you see there are
the basic functionalities: create, destroy, get, set and action.
Suppose that certain "attributes" are used to set up
relationships; when you receive a set request, the attribute
value is a DN. But of course, in your actual object, you don't
support arbitrary relationships; the relationship depends on the
type of the target object. So in the set request, you ask the
directory service for the object (a pointer to the object, in
fact), and dynamic_cast it to the type you support. If the
dynamc_cast fails, you reject the request with an error; if it
succeeds, you establish the relationship (whatever that means in
the context of the object). Thus, for example, a connection
point or a termination point has an implementedBy relationship
(which in this case will normally be specified as an argument to
the constructor, rather than using a set method, later); the
only way to communicate it is via a DN, so you have to
dynamc_cast, and reject the argument if it isn't the right type
(e.g. if someone requests the creation of a termination point
implemented by an event forwarding discriminator).
As soon as you're dealing with any sort of middleware (even
middleware in the same process), you'll probably need
dynamc_cast at the receiving end---the middleware should not
know the details of what it is connecting. As soon as you have
to deal with multiple versions in the clients or the servers,
you're likely to need dynamic_cast as well---you can avoid it,
but avoiding it more or less comes down to reimplementing what
it does yourself. I suspect that there are other cases as well,
but I've had to deal with those two often enough in practice to
be aware of them. (When we implemented the system I described
above, dynamic_cast didn't exist yet in the language. So we
invented our own version of it. With a lot more work than would
have been necessary with direct support in the language.)
James Kanze (GABI Software) email:email@example.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34