To me such a situation "A needs to know B whilst B needs to know A" is
almost always a not well defined OO design. Only very few situation
might need this (I cant see one right away)...
Okay, one solution might be to define an interface class known to both
classes (e.g. send messages with the help of the interface to a
registered receiver).
Maybe you need something else. It would help, to tell a bit more why
you think you need this design...
All right, I'll try to explain it. I have an application with, let's
say, "Items" and "Agents". There is a many-to-one relationship between
the two; an "Item" is assigned an "Agent" to deal with it. An Agent
takes an Item and does a whole bunch of processing, and eventually
comes up with some kind of results. I know it's vague but that's the
best short explanation I can give. So let's say we start off with the
basics:
class Item {
};
class Agent {
public:
virtual ~Agent ();
};
Well, an Item has an ID (that's how the Agent refers to it) and
results. Since "results" are closely associated with "items", it seems
logical to nest a Result class in Item:
class Item {
public:
class Result { };
ID getID () const;
void setResults (const Result &r);
};
The Agent (which is intended to be a base class) has a utility
function that sets an Item's Results given the Item ID:
class Agent {
public:
virtual ~Agent ();
protected:
void setItemResults_ (ID id, const Item::Results &r);
};
Now, however, it's useful to allow the Agent to associate some kind of
Agent-specific context data with an Item that it's handling. Context
data is closely associated with an Agent, so:
class Agent {
public:
class Context { };
virtual ~Agent ();
protected:
void setItemResults_ (ID id, const Item::Results &r);
};
The Item can have an Agent::Context associated with it, and it's
convenient to store it with each Item, so add Agent::Context
management to Item:
class Item {
public:
class Result { };
ID getID () const;
void setResults (const Result &r);
Agent::Context * getContext () const;
void setContext (Agent::Context *) const;
private:
mutable Agent::Context *ctx_;
};
And voila, Item references Agent::Context but Agent references
Item::Result. That's the situation I got stuck in. There are many
solutions:
1. Move Context into Item -- this could be reasonable, I guess.
2. Move Result into Agent -- this does not make sense.
3. Make Context not nested (e.g. AgentContext).
4. Make Result not nested (e.g. ItemResult).
I ended up picking number 4. My second choice was number 1.
So, I got the code working by moving Result out of Item, so it's no
longer an issue -- but that was the situation.
Jason