1

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?

defibkid
  • 21
  • 3
  • 2
    When you forward declare like that, delete the .h include. The whole point is to remove that file from being referenced. – Taekahn Mar 27 '22 at 00:45
  • In agent.h remove `#include "location.h"` and use a forward declaration. In `gameObject.h` remove `#include "company.h"` and use a forward declaration, In company.h remove all of the includes and use forward declarations. – drescherjm Mar 27 '22 at 00:48
  • Please show a [mre]. – Sam Varshavchik Mar 27 '22 at 00:49
  • *"But GameObject is included before Agent's inheritance of the class is declared."* -- it is? Does your compiler give you a trace through your `#include` chain? This is one reason full error messages are useful. I'm guessing your compiler complains about the declaration of `Agent` coming via `agent.h` included via line 3 in `company.h`, included via line 4 from `gameobject.h`, included from... not sure since we don't have the source file that triggers the error, but it's probably included before the instance of `agent.h` that you are looking at. Please include a source file to complete [mre]. – JaMiT Mar 27 '22 at 01:04
  • 3
    Does this answer your question? [error: expected ')' before '\*' token in header](https://stackoverflow.com/questions/31886183/error-expected-before-token-in-header) Pay particular attention to the parts of the answer there that mention *replacing* an `#include` line with a forward declaration, not keeping both. – JaMiT Mar 27 '22 at 01:10

1 Answers1

-1

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.

Taekahn
  • 1,592
  • 1
  • 13
  • 16
  • 1
    Got it! I saw another comment suggesting this fix and it seems to have worked. Now I'm onto a whole new set of errors! But I am now able to generate companies and agents to my heart's content. – defibkid Mar 27 '22 at 01:54
  • @defibkid While this is a useful advice, it doesn’t address the problem: the error doesn’t come from the circular dependency but from a syntax error in one of the headers that propagates. So if you get rid of the include that causes the issue, another error will show up in the other place you’ll include the file. – Christophe Mar 27 '22 at 09:23
  • @Christophe yes. Fixing the syntax errors is important. But I chose to address the issue stated in the title and in the question “why can’t I break this circular dependency with forward declarations” as opposed to any bug or typo present. 10 years from now, are people who find this question by search going to be searching for missing semicolons or be searching for circular dependencies? Is being told to fix a typo in the presented code going to be useful? If after fixing the issues with his includes, the code doesn’t work, he should open up a new question if he can’t figure it out on his own. – Taekahn Mar 27 '22 at 13:12
  • Any other code issues aside he _does_ have a circular include issue. So even if he fixed all the syntax issues his core question would remain unaddressed. – Taekahn Mar 27 '22 at 13:16