创建 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
在 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;
这是我的第一个问题,所以对于我可能不知道的有关堆栈溢出的任何事情,我提前表示歉意!
我遇到的问题是我正在制作一个简单的 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
在 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;