如何在不同的类中使用相同的头文件以避免"use of undefined type"

How to use the same header files in different classes to avoid "use of undefined type"

本文关键字:type use undefined 文件 of      更新时间:2023-10-16

我目前正在用2D库编写一个简单的游戏,因为C++对我来说是一种新语言,而且Java是我的第一个流利的编程语言,也许一些坏习惯正在流向这种我不完全理解的语言。我在 Java 中这样做从来没有遇到过问题,但C++它会导致大量错误。由于我不希望将所有内容都塞进一个类/头文件中,因此我决定将它们拆分为包和不同的类,但是如果不在不同的地方包含相同的头文件,我似乎无法做到这一点。下面是一个示例。

项目.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

现在我需要所有这些包含,以便我可以存储必要的纹理,纹理和矩形来自在 Project.h 中用作命名空间的 API

我还需要一个 Project.h 中的类实例,UIManager ui;所以我可以在 Project.cpp 文件中使用它来调用方法

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

如果我正确理解您的问题,您希望避免多次包含头文件。
在这种情况下,您应该做的是使用包含防护。这可确保标头包含一次。或者,您可以在文件顶部使用#pragma once,但这是另一个讨论。

例:

#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或类似名称。

一个好的做法是在 .h 文件的开头和结尾添加:

#ifndef FILENAME_H
#define FILENAME_H

//Your code here
#endif

其中FILENAME_H对于每个 .h 文件都是唯一的。

这些是编译器预指令,它们不包含在可执行文件中,但会更改编译器的行为方式。

添加

这些,编译器不会为同一文件添加两次相同的文件。如果已加载,则不会加载。

考虑到比在C++,头文件在项目的每个文件上独立解析。

通常,解决方法是将您的代码更改为此...

#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

您可以使用宏 #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

这允许编译器在看到循环包含时进行编译而不会出错。 但是,如果可能的话,最好使用类前向声明,但这是一个完全不同的主题。

宏名称__UI_MANAGER_H____PROJECT_H__完全是随机选择的。 您可以选择使用不同的命名约定。

相关文章: