Home > Back-end >  Forward declarations not fixing class dependency loops
Forward declarations not fixing class dependency loops

Time:03-27

I'm rather new to C projects. I'm trying to build a project where a lot of the classes contain fields that are references to objects of other classes. "This company owns that location, that location is occupied by these agents, these agents work for that company."

As you can imagine, it's difficult to get the compiler to work through these class definitions without hitting a loop. I always used include guards in my files, and I've tried using forward declarations in the classes that kick up errors, but I'm still dealing with issues when I try and initialize some of these objects.

Here's the class giving me issues right now:

agent.h

#ifndef AGENT_H
#define AGENT_H
#include "gameObject.h"
#include "location.h"

class Agent : public GameObject {
    public:
    Location* currentLocation;
    GameObject* currentTarget;
};

#endif

I'm calling the constructor for Agent in my main.cpp file, and I get an error "expected class name before '{' token" for Agent : GameObject. But GameObject is included before Agent's inheritance of the class is declared.

gameObject.h

#ifndef GAMEOBJ_H
#define GAMEOBJ_H
#include <string>
#include "company.h"

class Company;

class GameObject {
  public:
    Company* owner;
}

#endif

GameObject only relies on a definition of the Company class to compile, so I go look at my Company class...

company.h

#ifndef COMPANY_H
#define COMPANY_H
#include "agent.h"
#include "location.h"
#include "network.h"
#include "project.h"

class Company {
  public:
    std::vector<Agent*> currentAgents;
    std::vector<Network*> currentNetworks;
    std::vector<Location*> currentLocations;
    std::vector<Project*> currentProjects;
}

#endif

Company references all the child classes of GameObject, so I thought adding forward declarations of those classes here would keep the loop from happening and allow Company to fully compile, but the same list of errors come up regardless of whether or not Company.h has...

class Agent;
class Network;
class Location;
class Project;

...or not.

Any glaring issues here?

CodePudding user response:

Per your example you are doing this:

#ifndef GAMEOBJ_H
#define GAMEOBJ_H
#include <string>
#include "company.h"

class Company;

class GameObject {
  public:
    Company* owner;
}

#endif

Pick one of
#include "company.h"
or
class Company;

Doing both, while not harmful is redundant.

If you find you need the #include for the actual implementation, you can then #include it in the .cpp file.

All the above advice applies to the contents of company.h as well, along with all your other files.

CodePudding user response:

Preliminary remark: You first need to check the syntax: you forgot the semi-column at the end of several class definitions. Most probably is a syntax error in a header causing the kind of error messages you mention.

Once the syntax is corrected, there are several topics to consider:

  1. Forward definitions to address circular dependencies: If everything would be in the same file, you'd probably go for the last approach for so interdependent classes: forward declaration of everything, then the definitions. So the forward declarations can't be an issue, as long as they are before the class definitions that need it.

  2. Packaging of the declarations in different headers: here, the headers should be self contained (see core guideline). So you'd include in each header only the headers that you need; the include guards should avoid cycles. After the preprocessing, the compiler would then anyway see something like in 1 and you wouldn't have an issue either.

  3. Coupling of classes: In your particular case, you have very coupled classes that really depend on each other. If you'd need all the headers most of the time, you may consider regrouping the interdependent classes in a same header.

However, if possible reconsider the design, and try to decouple the classes to reduce the need for such circular dependencies (see core guideline).

  • Related