【问题标题】:C++ Issues creating class objects and circular inclusionC++ 创建类对象和循环包含的问题
【发布时间】:2015-12-17 01:20:14
【问题描述】:

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

我遇到的问题是我正在制作一个简单的 SDL 程序,目前它只是应该在屏幕上绘制一个 PNG 图像(Assets/Board.png),但我遇到了很多错误两个类相互通信,我认为我有循环包含错误。但是我这几天一直在尝试解决这个问题,但我一直无法解决它。

这是我得到的错误:

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

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

P.S 我知道我不应该使用 std 命名空间,而是我必须写 std::foo,我知道,所以请不要对此发表评论!

【问题讨论】:

  • 你实际上不能这样做。因为ManagerRender 都存储了彼此的实例,所以您需要前向声明一个(或两个)并动态创建实例。您可以将它们存储为std::unique_ptr
  • 谢谢 paddy,但是我应该转发哪个类来声明 Manager 和 Render 类??c

标签: c++ visual-studio class compiler-errors syntax-error


【解决方案1】:

在 C++ 中,“所有权”是一个非常重要的概念。一个类“拥有”它的成员。问题是您有两个对象,并且您告诉编译器两者都“拥有”另一个对象,这是行不通的。您必须决定他们中的哪一个拥有另一个,并将其作为成员(或者可能都不拥有另一个)。至少一个类必须引用另一个类,而不是将其列为子/成员。最好的引用是指针。

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_) 
{}

【讨论】:

  • 谢谢,这就像一个魅力。我刚刚发表了一条评论,说明了你所说的。对于那些想知道的人!
  • @Cameron Bell - 这就是我首先要说的:1)您不需要标题中的包含,2)您应该使用前向引用。诚然,我没有提到您需要在 .cpp 文件中包含 both 标头。问:我在原帖中没有表达什么?
  • @paulsm4:您没有提到必须将Manager 成员更改为指针而不是实例。这是最重要的部分。
【解决方案2】:

建议: 1.去掉“Render.h”包括:

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

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

您可以简单地使用“forward declaration”,而不是包括整个类接口(.h 文件)。

这些链接可能会有所帮助:

C++ circular include

Headers and Includes: Why and How

【讨论】:

  • 我需要 #include "Render.h" int eh manager 头文件,因为我有以下行:Render Tex; @paulsm4
  • 关于前向声明,我不知道该写在哪里?
  • 抱歉 - 我没有注意到 Member.h 中的“Render Tex”成员。但是,相同的解决方案:只需在类定义之前使用前向声明。示例:class Render; 请查看我引用的链接,尤其是“包含的“正确方法”部分:cplusplus.com/forum/articles/10627
  • 好的,我加了一行:class Render;在 render.h 文件的开头,我添加了一行:class Manager;在 Manager.h 文件的开头。我现在只有 3 个错误:Manager::Tex 使用未定义的类 'Render' Render::Manager 使用未定义的类 'Manager' 和 Render::Manager 使用未定义的类 'Manager'
  • @paulsm4:这些类相互作为成员,转发声明和玩标题不会削减它。他需要修改类。
【解决方案3】:

好的,我想我已经解决了这个问题,感谢各种cmets。该解决方案可能并不优雅,但它确实有效。我没有在 Manager 标头中定义 Render Tex 变量,而是在 Manager.cpp 类中声明了它。完成后,我可以在 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;

【讨论】:

    猜你喜欢
    • 2011-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-08
    • 1970-01-01
    相关资源
    最近更新 更多