我目前正在用2D库编写一个简单的游戏,因为C ++对我来说是一种新语言,而Java是我的第一个流畅的编程语言,也许一些不良习惯正在流入这种语言,我并不完全了解。我在Java中从未遇到过这样的问题,但在C ++中它会导致大量错误。因为我不希望所有内容都塞进一个类/头文件中,所以我决定将它们分成包和不同的类,但是如果没有在不同的地方包含相同的头文件,我似乎无法做到这一点。这是一个例子。
Project.h
#ifndef PROJECT_H
#define PROJECT_H
#include "UIManager.h"//this is causing the error, when this, and the class instance is removed the program compiles and runs fine without error
using namespace gamelib;
class Project : public Game {
public:
Project(int argc, char* argv[]);
~Project();
void Update(int elapsed);
void Draw(int elapsed);
void Load();
/*Background*/
Texture * background;
Rectangle* backgroundRectangle;
UIManager ui;
};
#endif
UIManager.cpp
#include "UIManager.h"
void UIManager::load() {
startMenuBackground = new Texture();
startMenuBackground->Load("Sprites/Interface/Transparency.png", false);
startMenuRectangle = new Rectangle(0.0f, 0.0f, Graphics::GetWidth() / 2, Graphics::GetHeight() / 2);
}
UIManager.h
#ifndef UIMANAGER_H
#define UIMANAGER_H
#include "Project.h"
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif
现在我需要所有这些包含所以我可以存储必要的纹理,而Texture和Rectangle来自在Project.h中用作命名空间的API
我还需要Project.h中的类实例, UIManager ui; 所以我可以在Project.cpp文件中使用它来调用方法
如何在不解决所有这些错误的情况下解决这个问题?
答案 0 :(得分:1)
如果我正确理解您的问题,您希望避免多次包含头文件。
在这种情况下,你应该做的是使用Include guards。这确保了标题包含一次。您可以选择使用文件顶部的#pragma once
,但另一个discussion。{
例如:
#ifndef UIMANAGER_H // you may choose another name than "UIMANAGER_H"
#define UIMANAGER_H
// Your header file code and includes here.
// Do this for your header files.
#endif
现在,对其他头文件执行相同操作,而是命名宏 PROJECT_H
或类似文件。
答案 1 :(得分:0)
一个好的做法是在.h文件的开头和结尾添加:
#ifndef FILENAME_H
#define FILENAME_H
//Your code here
#endif
其中FILENAME_H对于每个.h文件都是唯一的。
这些是编译器预定义,它们不包含在可执行文件中,但会改变编译器的行为方式。
添加这些,编译器不会为同一个文件两次添加相同的文件。如果已加载,则无法加载。
考虑到在C ++中,头文件在项目的每个文件中独立解析。
答案 2 :(得分:0)
通常,修复方法是将您的代码更改为此...
#ifndef UIManager_H
#define UIManager_H
// It's pretty normal to put each class in its own header file.
#include "Texture.h"
#include "Rectangle.h"
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif // UIManager_H
由于您从未实例化任何一个对象,因此您并不需要完整的标题。
#ifndef UIManager_H
#define UIManager_H
// Since we only use pointers to the classes, we can forward declare the classes
class Texture;
class Rectangle;
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif // UIManager_H
答案 3 :(得分:-1)
您可以使用宏#ifndef和#define。这是一种常见的模式。例如,在您的UIManager.h文件中,具有以下内容:
#ifndef __UI_MANAGER_H__
#define __UI_MANAGER_H__
#include "Project.h"
//Rest of UIManager class definition
#endif
在Project.h文件中,有以下内容:
#ifndef __PROJECT_H__
#define __PROJECT_H__
#include "UIManager.h"
//Rest of Project class definition
#endif
这允许编译器在看到循环包含时编译时没有错误。但如果可能的话,最好使用类前向声明,但这完全是different topic。
宏名称__UI_MANAGER_H__
和__PROJECT_H__
完全是随机选择的。您可以选择使用不同的命名约定。