1

I have 2 classes written in 2 different files: router.h - router.cpp and topology.h - topology.cpp.

I will show the contents of the .h files because the .cpp ones contain only implementations.

router.h:

#ifndef _ROUTER_H_
#define _ROUTER_H_
#include <map>
#include "topology.h"

using namespace std;

class Router {

public:
    int id;
    map<Router, int> linkers;
    Topology topology;

    Router();
    Router(int id);
    void addLink(Router router, int cost);
    void delLink(Router router);

};

#endif

topology.h:

#ifndef _TOPOLOGY_H_
#define _TOPOLOGY_H_
#include "router.h"

class Topology {
public: 
    map<Router, int> graph;  
    Topology();
    void addNode(Router router, int cost);
    void delNode(Router router);
};

#endif

My question is, why at compilation I have an error that is caused by the unrecognized Router and Topology classes, even if I included the headers and I added ifndefs in order to not include files more than one?? I looked up on the internet, on stack also and didn't find anything about this problem.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055

2 Answers2

1

The problem in this code is that your Topology (Topology.h) uses Router objects passed by value: the compiler needs to have the full definition of Router. That's fine, so you include Router.h. However, your Router needs a full Topology object (not a pointer, not a reference) to work.

So you have a configuration where A needs B fully declared to be fully declared, and B needs A fully declared to be fully declared itself. That's a problem, as stated in comments, of Circular Dependencies.

What you should do is to avoid the Topology object in Router (you may need a pointer because a full object means copy and not shared instance). Use a forward declaration of Topology in Router.h (and #include "Topology" in Router.cpp) and declare your "topology" attribute as pointer/smart pointer/reference.

Sid
  • 31
  • 4
  • There's no need to use replace the `Topology` member. The circular dependency can be fixed by simply forward declaring `Router` in `topology.h` instead. – bames53 Apr 13 '15 at 21:35
1

router.h includes topology.h which skips including router.h due to include guards and then uses class Router in its definition which is not defined. The standard solution is to forward declare types (such as class Router;). Unfortunately std::map requires full types and using it with incomplete types is undefined behavior. To make the map compatible with incomplete types you can either use std::unique_ptr<map<Router, int>> (or some other pointer type) or boost::container::map<Router, int>>.

nwp
  • 9,623
  • 5
  • 38
  • 68