如何在不同的类中使用相同的头文件,以避免“使用未定义的类型”

时间:2014-11-28 23:08:54

标签: c++

我目前正在用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文件中使用它来调用方法

如何在不解决所有这些错误的情况下解决这个问题?

4 个答案:

答案 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__完全是随机选择的。您可以选择使用不同的命名约定。