简体   繁体   English

C ++:无效使用不完整类型

[英]C++: invalid use of incomplete type

First of all I want to apologize for my english. 首先,我要为我的英语道歉。 I'm afraid that is not my born language. 恐怕不是我的母语。 I'm going crazy with this code. 我为这个代码而疯狂。

I'm making a little engine to make games. 我正在制作游戏的小引擎。 I implemented a class called "process" that is the class that will inherit all the elements that make up the game. 我实现了一个名为“ process”的类,该类将继承构成游戏的所有元素。 What happens is that by implementing two of these elements so that inherit from "process" the compiler throws me the following error: 发生的是,通过实现其中的两个元素,以便从“进程”继承,编译器将抛出以下错误:

||=== Build: Debug in MotorSDL (compiler: GNU GCC Compiler) ===|
include/mainProcess.h  |6 | error: invalid use of incomplete type ‘class process’
include/declarativas.h |65| error: forward declaration of ‘class process’
include/exeControl.h   |6 | error: invalid use of incomplete type ‘class process’
include/declarativas.h |65| error: forward declaration of ‘class process’
/home/yawin/Dokumentuak/c/MotorSDL/src/engine.cpp |  | In destructor ‘virtual Engine::~Engine()’:
/home/yawin/Dokumentuak/c/MotorSDL/src/engine.cpp |11| warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
/home/yawin/Dokumentuak/c/MotorSDL/src/engine.cpp |  | In member function ‘void Engine::update()’:
/home/yawin/Dokumentuak/c/MotorSDL/src/engine.cpp |76| warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
||=== Build failed: 4 error(s), 2 warning(s) (0 minute(s), 0 second(s)) ===|

I have read many of the issues in this respect have been published on this forum before and I understand that the mistake is that I am not correctly using a class (the class "process") because not instantiate properly or because it lacks something to the class (a required method not implemented). 我已经阅读过许多有关这方面的问题,这些问题以前曾在此论坛上发布过,并且我了解到错误是我没有正确使用一个类(类“ process”),原因是未正确实例化或因为该类缺少某些内容。类(未实现的必需方法)。

But as I read and check my code I can't find where I'm making the mistake. 但是,当我阅读并检查我的代码时,找不到我在哪里出错了。 Is anyone able to see what I'm wrong? 谁能看到我的错?

Here is the source code: https://github.com/yawin123/SDLEngine 这是源代码: https : //github.com/yawin123/SDLEngine

"main.cpp" “ main.cpp”

#include <SDL2/SDL.h>
#include "declarativas.h"

int main()
{
    Engine *e = new Engine(true);
    e->newWindow("Hola mundo", SDL_WINDOW_OPENGL, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_RENDERER_ACCELERATED);

    e->newTask(new exeControl());
    do
    {
        e->run();
        SDL_Delay(1);
    }while(e->isRunning());

    e->destroyWindow();

    return 0;
}

"include/declarativas.h" “包括/declarativas.h”

#ifndef DECLARATIVAS_H
#define DECLARATIVAS_H

enum keyCode
{
    _esc,
    _1, _2, _3, _4, _5, _6, _7, _8, _9, _0,
    _minus, _plus,
    _backspace,
    _tab,
    _q, _w, _e, _r, _t, _y, _u, _i, _o, _p,
    _a, _s, _d, _f, _g, _h, _j, _k, _l,
    _z, _x, _c, _v, _b, _n, _m,
    _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12,
    _enter,
    _c_enter,
    _control,
    _l_shift,
    _comma,
    _point,
    _r_shift,
    _c_asterisk,
    _prn_scr,
    _alt,
    _caps_lock,
    _num_lock,
    _scroll_lock,
    _home,
    _c_home,
    _up,
    _c_up,
    _pgup,
    _c_minus,
    _left,
    _c_left,
    _c_center,
    _right,
    _c_right,
    _c_plus,
    _end,
    _c_end,
    _down,
    _c_down,
    _pgdn,
    _c_pgdn,
    _ins,
    _c_ins,
    _del,
    _c_del,
    _less,
    _equals,
    _greater,
    _asterisk,
    _r_alt,
    _r_control,
    _l_alt,
    _menu,
    _l_windows,
    _r_windows,
    _close_window,
    _FOO_KEY
};

class Engine;
class process;
class Ventana;

//Procesos
class mainProcess;
class exeControl;

#include "process.h"
#include "engine.h"
#include "Ventana.h"

#include "mainProcess.h"
#include "exeControl.h"

#endif // DECLARATIVAS_H

"include/process.h" “ include / process.h”

#ifndef PROCESS_H
#define PROCESS_H

#include "engine.h"
#include "declarativas.h"

class process
{
    public:
        process();
        process(Engine *e);
        virtual ~process();

        virtual void Update();

        int id;
        int father;

        void setEngine(Engine *e);

    protected:
        Engine *engine;
};

#endif // PROCESS_H

"src/process.cpp" “ src / process.cpp”

#include "process.h"

process::process(){return;}
process::process(Engine *e)
{
    setEngine(e);
}

process::~process()
{
    return;
}

void process::setEngine(Engine *e)
{
    engine=e;
}

void engine::Update()
{
    return;
}

"include/engine.h" “ include / engine.h”

#ifndef ENGINE_H
#define ENGINE_H

#include "Ventana.h"
#include "process.h"
#include "declarativas.h"

#include <SDL2/SDL.h>
#include <vector>
#include <iostream>
using namespace std;

class Engine
{
    public:
        Engine(bool debug=false);
        virtual ~Engine();
        void run();

        void newWindow(string i_title, int i_windowMode, int i_posX, int i_posY, int i_width, int i_height, int i_rendererMode);
        void destroyWindow();
        Ventana* ventana;

        /**Ciclo de ejecución**/
            void input();
            void update();
            void render();
        /*********************/

        /**Control de ejecución*******/
            bool isRunning();
            void isRunning(bool m_r);
            bool m_run=true;
        /*****************************/

        vector<process*> taskManager;   //Gestor de procesos
        int newTask(process *task);     //Dar de alta procesos

        SDL_Event event;    //Evento para controlar teclado
        bool key[_FOO_KEY]; //Array de teclas pulsadas

        /**Control de debug*******/
            bool isDebug;
            void Debug(string t);
            void Debug(int t);
            void Debug(float t);
        /************************/
};

#endif // ENGINE_H

"src/engine.cpp" “ src / engine.cpp”

#include "engine.h"

Engine::Engine(bool debug)
{
    isDebug=debug;
    SDL_Init(SDL_INIT_VIDEO);
}

Engine::~Engine()
{
    for(int i=0;i<taskManager.size();i++)
    {
        delete(taskManager[i]);
    }
    taskManager.clear();

    delete(ventana);
    SDL_Quit();
}

void Engine::newWindow(string title, int windowMode, int posX, int posY, int width, int height, int rendererMode)
{
    if(ventana)
    {
        destroyWindow();
    }
    ventana = new Ventana(title,windowMode,posX,posY,width,height,rendererMode);
}

void Engine::destroyWindow()
{
    delete(ventana);
}

void Engine::run()
{
    input();
    update();
    render();
}

void Engine::input()
{
    for(int i=0;i<_FOO_KEY;i++)
    {
        key[i]=false;
    }

    while (SDL_PollEvent(&event))
    {
        switch (event.type)
        {
            case SDL_QUIT: //Si pulsamos el botón de cerrar ventana
                key[_close_window]=true;
                break;

            case SDL_KEYDOWN:
                switch (event.key.keysym.sym)
                {
                    case SDLK_ESCAPE:
                        key[_esc]=true;
                        break;

                    default:
                        break;
                }
                break;

            default:
                break;
        }
    }
}
void Engine::update()
{
    for(int i=0;i<taskManager.size();i++)
    {
        taskManager[i]->Update();
    }
}
void Engine::render()
{
    ventana->render();
}

bool Engine::isRunning()
{
    return m_run;
}
void Engine::isRunning(bool m_r)
{
    m_run=m_r;
}

int Engine::newTask(process *task)
{
    taskManager.push_back(task);
    taskManager[taskManager.size()-1]->setEngine(this);
    return taskManager.size()-1;
}

void Engine::Debug(string t)
{
    if(isDebug)
        cout<<t<<endl;
}
void Engine::Debug(int t)
{
    if(isDebug)
        cout<<t<<endl;
}
void Engine::Debug(float t)
{
    if(isDebug)
        cout<<t<<endl;
}

"include/mainProcess.h" “ include / mainProcess.h”

#ifndef MAINPROCESS_H
#define MAINPROCESS_H

#include "process.h"

class mainProcess : public process
{
    public:
        mainProcess();
        virtual ~mainProcess();

        virtual void Update();
};

#endif // MAINPROCESS_H

"src/mainProcess.cpp" “ src / mainProcess.cpp”

#include "mainProcess.h"
mainProcess():process(){}
mainProcess::~mainProcess(){}

void mainProcess::Update()
{
    return;
}

"include/exeControl.h" “ include / exeControl.h”

#ifndef EXECONTROL_H
#define EXECONTROL_H

#include "process.h"

class exeControl : public process
{
    public:
        exeControl();
        virtual ~exeControl();

        virtual void Update();
};

#endif // EXECONTROL_H

"src/exeControl.cpp" “ src / exeControl.cpp”

#include "exeControl.h"

exeControl::exeControl():process(){}
exeControl::~exeControl(){}

void exeControl::Update()
{
    if(engine->key[_esc] || engine->key[_close_window])
    {
        engine->isRunning(false);
    }
}

I think you don't need the rest of the classes. 我认为您不需要其余的课程。 But if you need, you can find in the link to github above. 但是,如果需要,可以在上面的github链接中找到。

You have a circular inclusion issue. 您有一个循环收录问题。

process.h includes engine.h and engine.h includes process.h . process.h包括engine.hengine.h包括process.h You need to break this cycle. 您需要打破这个周期。 This is usually done with using forward declarations and pushing includes in the the source files. 通常使用前向声明并在源文件中推送包含内容来完成此操作。

At a quick glance it looks like you can do a forward declaration of process in engine.h and remove the include. 乍一看,您可以在engine.h对进程进行前向声明并删除包含。

Note: Often you include a header in the header file of a class and in the source file of the same class but it's not necessary in the header already includes it. 注意:通常,您会在类的头文件和同一类的源文件中包含头,但是在已经包含它的头中则没有必要。


Example Issue 示例问题

Foo.h

#ifndef FOO_H
#define FOO_H

#include "Bar.h"

class Foo
{
private:
    Bar* mBar; // Raw pointer should actually be an appropriate smart pointer type
};

#endif

Foo.cpp

// Nothing required here for this example

Bar.h

#ifndef BAR_H
#define BAR_H

#include "Foo.h"

class Bar
{
private:
    Foo mFoo;
};

#endif

Bar.cpp

// Nothing required here for this example

In the above there is a circular inclusion issue; 上面有一个循环包含问题; the include guards have nothing to do with fixing this issue. 包含卫士与解决此问题无关。 Furthermore, since Foo only uses a pointer to a Bar instance a forward declaration can be used to break the cycle. 此外,由于Foo仅使用指向Bar实例的指针,因此可以使用前向声明来中断循环。


Example Solution 示例解决方案

Foo.h

#ifndef FOO_H
#define FOO_H

// Note: #include "Bar.h" is removed
class Bar; // This forward declares the `Bar` class

class Foo
{
private:
    Bar* mBar; // Raw pointer should actually be an appropriate smart pointer type
};

#endif

Foo.cpp

#include "Bar.h"

Bar.h

#ifndef BAR_H
#define BAR_H

#include "Foo.h"

class Bar
{
private:
    Foo mFoo;
};

#endif

Bar.cpp

// Nothing required here for this example

You have a case of cyclic dependency here: Engine class uses process and process uses Engine . 您在这里有一个循环依赖的情况: Engine类使用processprocess使用Engine This is often an indicator of a flawed architecture. 这通常表明存在缺陷的体系结构。

If all you care for is resolving the compilation issue, forward declaration should do the trick: remove either "process.h" from "engine.h" (or vice versa) and declare 如果您只想解决编译问题,则前向声明应该可以解决问题:从“ engine.h”中删除“ process.h”(反之亦然)并声明

class process;

in the "engine.h" header. 在“ engine.h”标头中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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