Reputation: 376
Should circular dependency be avoided on graphs ?
For instance, consideer a graph
class embedding an array of vertex
objects, each of them having an array of edge
objects which point to a vertex
.
Here, vertex
and edge
are circularly dependent. Is this a bad idea ? Should it and how could it be avoided ?
Upvotes: 2
Views: 1681
Reputation: 10880
No, it shouldn't. Graphs that have a non-trivial edge and vertex classes are inherently circular-dependent. If edge
is practically empty, you might just store the adjacency matrix (i.e., whether there's an edge between given vertices); if vertex
is empty, you might store and edge list that stores vertex number (size_t) instead of pointer.
Best practice is to use smart_ptr<> and weak_ptr<> to break the chain. The latter is non-owning, thus:
graph
class has vector< smart_ptr< vertex > >
vertex
class has vector< smart_ptr< edge > > m_out;
and optionally vector< weak_ptr< edge > > m_in;
edge
class has weak_ptr< vertex > m_vertices[2];
(or better yet m_from and m_to)graph
class has vector< smart_ptr< edge > >
edge
class has smart_ptr< vertex > m_from;
and weak_ptr< vertex > m_to;
vertex
class has vector< weak_ptr< edge > > m_out;
and optionally vector< weak_ptr< edge > > m_in;
If, for some reason (like widsom of senior :), coding standard, etc.) you cannot use smart_ptr<> and weak_ptr<>, you might use references instead of weak pointers, those are generally considered non-owning. Instead of smart_ptr<> you might either use pointers - or why not have members as long as edge
and vertex
are not base classes. Stroustrup additionally recommends marking naked pointers that should be deleted on exit using owner<>
. If you don't have it, you might define a no-op for it as template<typename T> using owner = T;
.
Upvotes: 3