Path: utzoo!attcan!uunet!brunix!sdm From: sdm@cs.brown.edu (Scott Meyers) Newsgroups: comp.lang.c++ Subject: Design Problem Message-ID: <22137@brunix.UUCP> Date: 3 Dec 89 21:23:29 GMT Sender: news@brunix.UUCP Reply-To: sdm@cs.brown.edu (Scott Meyers) Organization: Brown University Department of Computer Science Lines: 48 I'm having trouble figuring out how to solve the following problem. Often I find myself with a collection of objects of a given type, where some of them define a particular function and some of them don't, and I want to invoke the function on only those objects for which it is defined. For example, I might have a collection of objects of type B, but only those objects of type D (derived from B) define a function f; I'll want to invoke f on those objects for which it is defined. How can I best accomplish this? To make things more concrete, I'm building graphs for representing programs, and one of my base types is ARC. Derived from ARC are two classes, EXECUTABLE_ARC and NONEXECUTABLE_ARC. Each of these types also have subtypes, but that is immaterial. EXECUTABLE_ARCs define a function evaluate(); NONEXECUTABLE_ARCs do not. The graph for a program consists of a set of nodes and a set of arcs, and to execute the program, I need to evaluate the nodes and arcs. So what I have is a set of ARCs, and I want to call evaluate() on them, but only some of them define that function. It seems I have three possible approaches: 1. Define evaluate() as a virtual function in ARC, and redefine it appropriately in EXECUTABLE_ARC. In ARC, make it a noop, so when called on NONEXECUTABLE_ARCs, it won't do anything. 2. Add an enumerated type to ARC that enumerates each of the subtypes, and add a virtual function arc_type() that is redefined in each subclass to return the appropriate value. Then I can write code like "if (arc->arc_type() == EXECUTABLE) arc->evaluate()". 3. Separate my ARC class into two distinct classes, so I never have this problem. None of these designs is attractive. The first one doesn't extend well to situations in which there may be many functions like evaluate() down in the hierarchy -- each will have to be defined in ARC, even though they have nothing to do with generic ARCness. In addition, it suffers from the same problem that the second one does: adding new classes to the hierarchy may require that I modify the base class (e.g., adding new enumerated type values). The third option is impractical because, although the class ARC breaks down well along executability, there are many other aspects of ARCs that don't separate so easily -- I really do want to have a single ARC superclass. What I really want to be able to say is "if function f() is defined for object o, then call o.f()". Is there a good way to acheive this effect? Scott sdm@cs.brown.edu