Progam Design Suggestions

Hey everyone,

So I have a setup right now where two classes are co-dependent: class C1 holds a list of class C2 objects and performs actions on them, and each C2 objects holds a pointer to its parent C1 object so that it can call functions from it as necessary. Obviously, this is a problem, since it requires cyclic definitions. Here are some solutions I've thought of:

-Create a third class C3 that handles requests from C2 to C1. I'm unsure of whether this'll result in the same cyclical problems.
-Implement a purely abstract class C2' that C2 derives from. This allows C2' to simply set the C1 parent pointer, and only C2 itself has to worry about specific function calls. I've done something like this on an old project but I have a sneaking suspicion that this is bad coding form.

Any other suggestions or feedback on the above two would be much appreciated. Thanks a lot in advance!
Besides the fact that C1 and C2 are tied together closely, which isn't going to be corrected by your suggestions, what is your problem? Seems like a usual undirected composition to me.
The problem is that as it stands, C1 calls methods from C2, and thus requires C2 to be defined and compiled before C1 can be defined and compiled. However, C2 also calls methods from C1, thus requiring C1 to be defined and compiled first. I'm looking for a way around this little paradox.

I've never heard the term "undirected composition" before, could you explain what it is?
It's not cyclic if C2 only has a pointer to the C1.
@guestgulkan

Hm. My current setup is such that C2 does only have a pointer to C1, as in the following:

1
2
3
4
5
6
7
8
9
10
class C2
{
   private:
      C1 *parentPointer;
   public:
      C2(C1 *c1ptr)
      {
         parentPointer = c1ptr;
      }
}


And then later on, there's the following:

1
2
3
4
void foo()
{
   parentPointer->bar();
}


I think this is what you mean by only maintaining a pointer to C1. As it stands, I get a lot of "C2 was not defined in this scope" errors when C2 contains methods that call methods from C1. However, when C2 contains no such methods, but derived classes of C2 do, everything works fine and dandy.
Last edited on
I've never heard the term "undirected composition" before, could you explain what it is?

It's a composition (i.e. a "consists-of" relationship) where the part has a association ("knows"-relationship) to the whole. In C++, this is implemented as
1
2
3
4
class whole;
class part{ whole* w; ...};

class whole{ part p; ...};

(alternative, "whole" might use a pointer for "part", too, e.g. to minimize compile-time dependencies by only providing a forward declaration in the header file. For a composition, the requirement then is usually stated as "they live and go together", i.e., the constructor of part is called as a part of whole's constuctor, and so is the destructor. Otherwise it is formulated as a aggregation ("consists-of" relationship)).

Edit.
In your post above, you have to provide a forward declaration for C1, of course.
Last edited on
It would be easier to understand and suggest if you could provide a brief description of the problem.
Even in above suggested whole and part undirected composition, either aggregation (loose coupling) or composition (tight coupling), the cyclic relationship is not recommended. A whole is set of parts, but not other way around.

Take an example of a customer order (as a header/container) and its order details.
In C++, you would design it as Order and Item Detail classes, where Order is a container
which has a list of references to the pertinent item objects and each Item object has
all the methods that needs to.
Since the container has references to the items, it could have a method called CalculateOrderTotal()
which in turn calls the Item's ItemTotal() for each item belongs to the "parent" order.
That is, the call goes from the container to the continee, but not otherway around.

In an RDBMS like Oracle, you would design the same as Header(Order) and Detail(Item) tables, where each Detail row would have a foreign key referencing to the parent OrderId in the header Order table.
And the calculations are done on fly in an SQL query. You could also design/define functions in OO style ORACLE programming.

As you notice it above, it would not be cyclic. Again, it could vary form the requirment and design.

If you could provide a brief description of the problem it would give us better idea of the requirement and we could come up with some suitable suggestions.

Check it out. Good luck :)
Last edited on
@exception: of course. Forgot to put that in the example there :)

@satm2008: there's no existing problem, per se. I just have a design idea that was based on a cyclic relationship and I was looking for ways to get around it.

Either way, you've all been a great help and I think I understand a little bit more about how to get around what my problem is. Thanks a lot, everyone!
Topic archived. No new replies allowed.