简体   繁体   中英

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

I'm currently writing a simple game with a 2D library and as C++ is a new language to me and as Java is my first fluent programming language, perhaps some bad habits are flowing through to this language that I don't fully understand. I have never had problems doing this in Java but in C++ it causes a ton of errors. As I don't want everything crammed into one class/header file, I've decided to split them up into packages and different classes, but I can't seem to do this without includng the same header files in different places. Here's an example.

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

Now I need all of these includes so I can store the necessary textures, and the Texture and Rectangle come from the API that is being used as a namespace in Project.h

I also need a class instance in Project.h, UIManager ui; So i can use this in the Project.cpp file to call methods

How can I get around this without getting all these errors?

If I understand your problem correctly, you want to avoid including header files multiple times.
In that case, what you should do is using Include guards . Which makes sure that the header is included once. Optionally you can use #pragma once at the top of your file but that's another discussion .

Example:

#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

Now, do the same for the other header file but instead naming the macro PROJECT_H or similar.

A good practice is to add in the beginning and in the end of the .h files:

#ifndef FILENAME_H
#define FILENAME_H


//Your code here

#endif

Where FILENAME_H is unique for each .h file.

Those are compiler predirectives, which are not included in the executable, but changes the way that the compiler acts.

Adding those, the compiler won't add the same file twice for the same file. If it's already loaded, it won't load it.

Take in account than in C++, header files are parsed independently on each file of the project.

Typically, the fix would be to change your code to this...

#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

Since you never instantiate either object though, you don't strictly need a full header.

#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

You can use the macros #ifndef and #define. This is a common pattern. For example, in your UIManager.h file, have the following:

#ifndef __UI_MANAGER_H__
#define __UI_MANAGER_H__

#include "Project.h"
//Rest of UIManager class definition


#endif

In you Project.h file, have the following:

#ifndef __PROJECT_H__
#define __PROJECT_H__

#include "UIManager.h"
//Rest of Project class definition


#endif

This allows the compiler to compile without errors when it sees circular includes. But it's more preferable to use class forward declaration if possible, but this is a completely different topic .

The macro names __UI_MANAGER_H__ and __PROJECT_H__ are purely randomly chosen. You can choose to use a different naming convention.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM