C++ – How to Resolve Class Interdependence

cclassclass-design

In my C++ project, I have two classes, Particle and Contact. In the Particle class, I have a member variable std::vector<Contact> contacts which contains all contacts of a Particle object, and corresponding member functions getContacts() and addContact(Contact cont). Thus, in "Particle.h", I include "Contact.h".

In the Contact class, I would like to add code to the constructor for Contact that will call Particle::addContact(Contact cont), so that contacts is updated for both the Particle objects between which the Contact object is being added. Thus, I would have to include "Particle.h" in "Contact.cpp".

My question is whether or not this is acceptable/good coding practice and, if not, what would be a better way to implement what I am trying to achieve (simply put, automatically updating the list of contacts for a specific particle whenever a new contact is created).


These classes will be tied together by a Network class that will have N particles (std::vector<Particle> particles) and Nc contacts (std::vector<Contact> contacts). But I wanted to be able to have functions like particles[0].getContacts() – is it okay to have such functions in the Particle class in this case, or is there a better association "structure" in C++ for this purpose (of two related classes being used in another class).


I may need a perspective shift here in how I am approaching this. Since the two classes are connected by a Network class object, is it typical code/class organization to have connectivity information entirely controlled by the Network object (in that a Particle object should not be aware of its contacts and, consequently, it should not have a getContacts() member function). Then, in order to know what contacts a specific particle has, I would need to obtain that information through the Network object (e.g., using network.getContacts(Particle particle)).

Would it be less typical (perhaps even discouraged) C++ class design for a Particle object to have that knowledge, as well (i.e., have multiple ways to access that information — through either the Network object or the Particle object, whichever seems more convenient)?

Best Answer

There are two parts in your question.

The first part is the organization of C++ header files and source files. This is solved by using forward declaration and the separation of the class declaration (putting them in the header file) and method body (putting them in the source file). Furthermore, in some cases one can apply the Pimpl idiom ("pointer to implementation") to solve harder cases. Use shared-ownership pointers (shared_ptr), single-ownership pointers (unique_ptr), and non-owning pointers (raw pointer, i.e. the "asterisk") according to best practices.

The second part is how to model objects that are inter-related in the form of a graph. General graphs that are not DAGs (directed acyclic graphs) don't have a natural way of expressing tree-like ownership. Instead, the nodes and connections are all metadata that belong to a single graph object. In this case, it is not possible to model the node-connection relationship as aggregations. Nodes don't "own" connections; connections don't "own" nodes. Instead, they are associations, and both nodes and connections are "owned by" the graph. The graph provides query and manipulation methods that operate on the nodes and connections.

Related Topic