0

This is my first question, so I apologize in advance for any things about stack overflow that I may not be aware of!

The issue I am having is that I am making a simple SDL program, currently it is just supposed to draw a PNG image (Assets/Board.png) to the screen, but I am being faced with many errors to do with the two classes communicating with each other, I think that I have circular inclusion errors. But I have been trying to fix the problem for days and I haven't been able to solve it.

Here are the errors that I am getting:

https://i.stack.imgur.com/kEVXN.png

(Here is a text version of it, but the formatting is bad sorry)

1>d:\code\c++\games\chess\chess\manager.h(41): error C2079: 'Manager::Tex' uses undefined class 'Render'
1>d:\code\c++\games\chess\chess\render.h(32): error C2146: syntax error : missing ';' before identifier 'manager'
1>d:\code\c++\games\chess\chess\render.h(32): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\code\c++\games\chess\chess\render.h(32): error C2146: syntax error : missing ';' before identifier 'manager'
1>d:\code\c++\games\chess\chess\render.h(32): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

(I have used an image because the formatting of the image is easier to read.) (Also click on the image in imgur to see the zoomed in version)

You can download the entire code project here (ZIP FILE):

https://www.mediafire.com/?og21315fc1d58sk

But here is the code that I think is causing the issues:

(Manager.h file)

//Include guards.
#pragma once

//Headers.
#include "Render.h"

//Librarys.
#include <SDL_image.h>
#include <string>
#include <SDL.h>

//Namespaces.
using namespace std;

//Enumerator.
enum State { Play, Exit };

class Manager
{
public:
    Manager(); //Constructor.
    ~Manager(); //Destructor.

    //Rendering.
    SDL_Window* Window;
    SDL_Surface* Screen;
    SDL_Renderer* Renderer;

    //Functions.
    void Run();
    void Init();
    void Close();
    void Input();
    void Update();
    void Error(string);

    //Game variables.
    State state;
    Render Tex;

private:

    //Constant values.
    const int WINDOW_POS_X = SDL_WINDOWPOS_CENTERED;
    const int WINDOW_POS_Y = SDL_WINDOWPOS_CENTERED;
    const int INIT_FLAGS = SDL_INIT_VIDEO;
    const int SCREEN_HEIGHT = 600;
    const int SCREEN_WIDTH = 600;
};

(And here is the Render.h file)

//Include guards.
#pragma once

//Headers.
#include "Manager.h"

//Librarys.
#include <SDL_image.h>
#include <string>
#include <SDL.h>

//Namespaces.
using namespace std;

class Render
{
public:
    Render(); //Constructor.
    ~Render(); //Destructor.

    //Functions.
    void Draw(int, int); //Draws texture at position.
    void Load(string); //Loads texture from path.
    void Deallocate(); //Destroy texture.

    //Getter functions.
    int GetHeight() { return Height; };
    int GetWidth() { return Width; };

private:
    SDL_Texture* Texture; //Actual image.
    Manager manager; //Manager class.

    int Height; //Height of image.
    int Width; //Wdith of image.
};

So in conclusion, I am having errors related to the class objects, which I believe are being caused by circular inclusion, despite my research I have not been able to fix these issues. I would greatly appreciate any help with this issue.

P.S I know I am not supposed to use the std namespace, instead I must write std::foo, I am aware, so please don't comment about it!

  • 1
    You actually can't do it like this. Because `Manager` and `Render` each store an instance of eachother, you will need to forward-declare one (or both) and create instances dynamically. You can store them as a `std::unique_ptr`. – paddy Dec 17 '15 at 01:24
  • Thanks paddy, but what class would I forward declare the Manager and Render classes??c –  Dec 17 '15 at 01:28

3 Answers3

0

SUGGESTIONS: 1. Eliminate the "Render.h" include:

There doesn't seem to be anything in "Manager.h" that needs anything in "Render.h" - so why include it?

Similarly, 2. Eliminate the "Manager.h" include.

You can simply use a "forward declaration", instead of including the whole class interface (.h file).

These links might help:

C++ circular include

Headers and Includes: Why and How

Community
  • 1
  • 1
paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • I need to #include "Render.h" int eh manager header file because I have the line: Render Tex; @paulsm4 –  Dec 17 '15 at 01:29
  • And about the forward declaration, I do not know where I should write that? –  Dec 17 '15 at 01:31
  • Sorry - I didn't notice the "Render Tex" member in Member.h. Same solution, however: just use a forward declaration before your class definition. EXAMPLE: `class Render;` Please look at the links I cited, especially " "The 'right way' to include" section here: http://www.cplusplus.com/forum/articles/10627/ – paulsm4 Dec 17 '15 at 01:33
  • Okay I added the line: class Render; at the beggining of the render.h file, and I added the line: class Manager; at the beggining of the Manager.h file. I now only have 3 errors: Manager::Tex uses undefined class 'Render' Render::Manager uses undefined class 'Manager' and Render::Manager uses undefined class 'Manager' –  Dec 17 '15 at 01:36
  • @paulsm4: The classes have each other as members, forward delcaration and playing with headers won't cut it. He needs to modify the classes. – Mooing Duck Dec 17 '15 at 01:38
  • @MooingDuck , Well if that is the case, then what sort of modification to to classes should I make? –  Dec 17 '15 at 01:39
  • @Cameron Bell: important point: you *can* and *should* include *both* "Render.h" and "Manager.h" in each of "Render.cpp" and "Manager.cpp" (your implementation files). Again, please read [this](http://www.cplusplus.com/forum/articles/10627/) and see if it's applicable to your scenario. I believe that it is, and that it can help. – paulsm4 Dec 17 '15 at 01:41
0

In C++ "ownership" is a very important concept. A class "owns" its members. The problem is you have two objects and you've told the compiler that both "own" the other, which won't do. You have to decide which of them owns the other, and has it as a member (or maybe neither owns the other). At least one class must refer to the other, rather than listing it as a child/member. And the best sort of reference is a pointer.

class Manager; 
// this forward declaration tell the compiler the class exists, but 
// we don't care about the details yet, so we won't include the header.
// if we try to include it, that header refers to Render, which the compiler
// hasn't seen yet, so the compiler will fail.
class Render
{
public:
    Render(Manager* parent_); //Constructor.
    ...stuff...
    Manager* parent;
};

Cpp file:

#include "manager.h"
#include "render.h"
Render::Render(Manager* parent_)
    : parent(parent_) 
{}
Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
  • Thanks, that works like a charm. I just posted a comment that says what you said. for those who were wondering! –  Dec 17 '15 at 01:48
  • @Cameron Bell - that's what I tried to say in the first place: 1) you don't need the includes in the header, and 2) you should use a forward reference instead. Admittedly, I didn't mention that you *also* need to include *both* headers in the .cpp file. Q: What did I fail to express in my original post? – paulsm4 Dec 17 '15 at 03:57
  • @paulsm4: You didn't mention that you have to change the `Manager` member to be a pointer rather than an instance. That's the most important part. – Mooing Duck Dec 17 '15 at 17:57
0

Okay, I think that I have solved the problem, thanks to a variety of comments. The solution may not be ellegant but it works. Instead of defining the Render Tex variabel inside the Manager header, I declared it inside the Manager.cpp class. Once I had done that I can #include "Render.h" inside the Manager .cpp file. I dont know if that explanation is clear but here is the top of the manager.h file:

//Include guards.
#pragma once

//Librarys.
#include <SDL_image.h>
#include <string>
#include <SDL.h>

And here is the top of the Manager.cpp file:

//Header.
#include "Manager.h"
#include "Render.h"

//Librarys.
#include <iostream>

//Objects.
Render Tex;