创建 class 对象和循环包含的 C++ 问题

C++ Issues creating class objects and circular inclusion

这是我的第一个问题,所以对于我可能不知道的有关堆栈溢出的任何事情,我提前表示歉意!

我遇到的问题是我正在制作一个简单的 SDL 程序,目前它只是应该在屏幕上绘制一个 PNG 图像 (Assets/Board.png),但我面临着很多与两个 classes 相互通信有关的错误,我认为我有循环包含错误。但是我这几天一直在努力解决这个问题,一直没能解决。

这是我遇到的错误:

http://imgur.com/gallery/vq3XLwU/new

(这是它的文本版本,但是格式不好抱歉)

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

(我使用了一张图片,因为图片的格式更容易阅读。) (也可以点击 imgur 中的图片查看放大版本)

您可以在此处下载整个代码项目(ZIP 文件):

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

但我认为这是导致问题的代码:

(Manager.h 文件)

//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;
};

(这里是 Render.h 文件)

//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.
};

所以总而言之,我遇到了与 class 对象相关的错误,我认为这是由循环包含引起的,尽管我进行了研究但仍无法解决这些问题。我将不胜感激任何对此问题的帮助。

P.S 我知道我不应该使用 std 命名空间,相反我必须写 std::foo,我知道,所以请不要评论它!

建议: 1.去掉"Render.h"包括:

"Manager.h" 中似乎没有任何东西需要 "Render.h" 中的任何东西 - 那么为什么要包含它?

同理,2.去掉"Manager.h"包含。

您可以简单地使用“forward declaration”,而不是包含整个 class 界面(.h 文件)。

这些链接可能有帮助:

C++ circular include

Headers and Includes: Why and How

在 C++ 中 "ownership" 是一个非常 重要的概念。 A class "owns" 其成员。问题是你有两个对象,你已经告诉编译器两个 "own" 另一个,这是行不通的。您必须决定他们中的哪一个拥有另一个,并将其作为成员(或者可能都不拥有另一个)。至少有一个 class 必须 引用 另一个,而不是将其列为 child/member。最好的参考是指针。

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 文件:

#include "manager.h"
#include "render.h"
Render::Render(Manager* parent_)
    : parent(parent_) 
{}

好的,我认为我已经解决了问题,感谢各种评论。该解决方案可能并不优雅,但它确实有效。我没有在管理器 header 中定义 Render Tex 变量,而是在 Manager.cpp class 中声明了它。完成后,我可以在 Manager .cpp 文件中#include "Render.h"。我不知道这个解释是否清楚,但这是 manager.h 文件的顶部:

//Include guards.
#pragma once

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

这里是 Manager.cpp 文件的顶部:

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

//Librarys.
#include <iostream>

//Objects.
Render Tex;