Re: Visitor, dynamic_cast or ...
From: H. S. Lahman (h.lahman_at_verizon.net)
Date: 10/25/03
- Next message: Hong Ling: "Check out this internet patch"
- Previous message: DPfan: "Singleton"
- In reply to: Ares Lagae: "Visitor, dynamic_cast or ..."
- Next in thread: Daniel T.: "Re: Visitor, dynamic_cast or ..."
- Reply: Daniel T.: "Re: Visitor, dynamic_cast or ..."
- Reply: Dave Harris: "Re: Visitor, dynamic_cast or ..."
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Sat, 25 Oct 2003 20:58:55 GMT
Responding to Lagae...
> Each time i run into the same problem. I have a base class with sometimes as
> less as 2 derived classes. I put them in some datastructure (so i do need
> the base class (even with type safe containers like the ones in stl)). Then
> off course i loose type information. Sometimes this can be solved with
> virtual functions, sometimes not. In the cases where it cannot be solved
> with virtuals ,each time i find myselve considering these solutions:
>
> (1) use visitors
> (2) use dynamic_cast
> (3) group everything into a single class
As soon as dynamic_downcast becomes a viable alternative one should be
suspicious that there are missing relationships. (There are exceptions
but they involve external object streams where one cannot know the type
of a particular object and there are no other language facilities to
deal with determining the type.)
>
> (2) i dont like dynamic_cast, also because it incurs a performance penalty
> (1) is faster than (2) but can lead to very awkward implementations
> sometimes (see further)
> (3) dont like this one
>
> To illustrate my problem: suppose you are building a set of classes to work
> with octrees. For those of you that are not familiar with octrees: An octree
> is a datastructure similar to a binary search tree. Start with a cube.
> Divide the cube into 8 equal octants, recursively apply the subdivision to
> some cells. This way you end op with a tree with two kinds of nodes:
> internal nodes have (exactly) 8 children, the children can be leaf nodes or
> internal nodes, the 8 children are not necesarily of the same type. Leaf
> nodes contain some data. This data structure can be used for range queries
> (like a kd-tree, but splits up each of the 3 dimensions in each node), or to
> represent sparse 3d arrays of data (cells with equal data are grouped).
> Octrees are used to represent such sparse grids that would otherwise not fit
> in memory.
The basic octree seems very similar a basic Composite pattern:
0..1 1 *
[Client] ----------- [Node] --------------+
A |
| |
+-------+------+ |
| | 1 |
[Leaf] [Internal] ----+
The difference is that the [Internal] nodes do not share behaviors with
[Leaf] nodes (e.g., operation() in the GoF pattern). That is, the
[Internal] nodes are purely navigational while the [Leaf] nodes have the
properties a Client actually wants.
That suggests that there are two relationships between [Client] and the
octree. One relationship is used purely for navigation to get to a
particular Leaf. Once the Leaf is reached, the other relationship is
instantiated:
1 navigates 1
[Client] --------------------- [OcTree]
| 1 | 0..1
| |
| currently accesses | starts at
| 1 | 1
[Leaf] [Internal] ----------+
| | 1 |
| | |
+--------------+----------------+ |
| |
- |
V |
[Node] ------------------------------+
* parent of
In this case the intelligence of navigating the Composite-like tree
lives in [OcTree]. For example, it might have a Find(key) method that
is accessed by [Client] that always returns a Leaf reference. Since the
distinction between [Leaf] and [Internal] is purely a matter of
navigating the tree (i.e., that a limb is terminated), [OcTree] does not
have to understand which subclass it has in hand in any behavioral
sense. So one can use a simple type attribute to distinguish [Leaf] vs.
[Internal] for navigation purposes. Or one can incorporate that into
the [Node] identity key (e.g., setting the MSB).
When OcTree.Find returns a Leaf, that effectively instantiates the
[Client]/[Leaf] relationship. So [Client] does not know that [Internal]
nodes even exist.
[Note that the 1:* relationship being fixed at 8 allows additional
optimization at the OOP level because it can be a fixed array of Node*
references.]
This yields a fairly simple and efficient view of the tree that doesn't
require complexities like Visitor, nastiness like dynamic_downcast, or
god classes. However, that is only accomplished by separating the
concerns of tree navigation from leaf processing (i.e., by implementing
and navigating a second relationship).
*************
There is nothing wrong with me that could
not be cured by a capful of Drano.
H. S. Lahman
hsl@pathfindermda.com
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindersol.com
(888)-OOA-PATH
- Next message: Hong Ling: "Check out this internet patch"
- Previous message: DPfan: "Singleton"
- In reply to: Ares Lagae: "Visitor, dynamic_cast or ..."
- Next in thread: Daniel T.: "Re: Visitor, dynamic_cast or ..."
- Reply: Daniel T.: "Re: Visitor, dynamic_cast or ..."
- Reply: Dave Harris: "Re: Visitor, dynamic_cast or ..."
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|