C++ 前向声明错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4197106/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:48:32  来源:igfitidea点击:

C++ forward declaration error

c++forward-declaration

提问by John Dibling

I have an error that goes like this

我有一个像这样的错误

    In file included from Level.hpp:12,
                 from main.cpp:4:
Corridor.hpp: In method `void Game::Corridor::update()':
Corridor.hpp:41: invalid use of undefined type `class Game::Level'
Corridor.hpp:13: forward declaration of `class Game::Level'
Corridor.hpp:42: invalid use of undefined type `class Game::Level'
Corridor.hpp:13: forward declaration of `class Game::Level'
Corridor.hpp:43: invalid use of undefined type `class Game::Level'
Corridor.hpp:13: forward declaration of `class Game::Level'
Corridor.hpp:44: invalid use of undefined type `class Game::Level'
Corridor.hpp:13: forward declaration of `class Game::Level'

Corridor and Level are ...

走廊和楼层是...

  // Corridor.hpp

#ifndef GAME_CORRIDOR_HPP
#define GAME_CORRIDOR_HPP

#include <Moot/Math.hpp>

//#include <Level.hpp>
#include <GameWindow.hpp>

namespace Game
{
    class Level; // <-- LINE 13

    class Corridor
    {
        static const unsigned int defaultLevelDepth = 800;

        Moot::Math::Vector3D wp1, wp2, wp3, wp4;
        Moot::Math::Vector2D sp1, sp2, sp3, sp4;

        Level * p_level;

    public:

        Corridor(Moot::Math::Vector3D setFirstPoint, Moot::Math::Vector3D setSecondPoint) 
        {
            wp1 = setFirstPoint;
            wp2 = setSecondPoint;

            wp3 = setFirstPoint;
            wp3.z += defaultLevelDepth;

            wp4 = setSecondPoint;
            wp4.z += defaultLevelDepth;
        }


        void update() {

            sp1 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp1); // <- LINE 41 etc.
            sp2 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp2);
            sp3 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp3);
            sp4 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp4);


            //p_level->getLevelCamera();
        }

        void draw()//const
        {
            Moot::Color tempColor;

            windowInstance().graphics().drawQuad( sp1.x, sp1.y, tempColor,
                                                                                sp2.x,sp2.y, tempColor,
                                                                                sp3.x, sp3.y, tempColor,
                                                                                sp4.x,sp4.y, tempColor, 1);
        }


        void setLevel(Level* setLevel) {
            p_level = setLevel;
        }

    };
}

#endif

and

// Level.hpp

#ifndef GAME_LEVEL_HPP
#define GAME_LEVEL_HPP

#include <Moot/Forward.hpp>
#include <Moot/Window.hpp>
#include <Moot/Math.hpp>

#include <GameWindow.hpp>
#include <Camera.hpp>
#include <Corridor.hpp>
#include <Player.hpp>

#include <vector>


namespace Game
{
    class Level
    {

        typedef Corridor* p_corridor;
        typedef std::vector<p_corridor> CorridorList;
        typedef CorridorList::reverse_iterator ReverseCorridorItter;

        CorridorList m_map;
        Camera       m_camera;
        Player         m_player;


    public:

        Level()
        {
            m_player.setLevel(this);

            // Lots of vertices being defined into m_map.


            // Loop through and set camera
            ReverseCorridorItter rit;

            for(rit = m_map.rbegin(); rit != m_map.rend(); rit++)
                (*rit)->setLevel(this);


        }


        ~Level()
        {
            ReverseCorridorItter rit;

            for(rit = m_map.rbegin(); rit != m_map.rend(); rit++) 
                delete (*rit);

            m_map.clear();
        }


        void update() 
        {
            // Temp delete when input and player are implimented.
            if(pad[0].buttons & PAD_UP)
                m_camera.updateTargetOffsets(0, -2);

            if(pad[0].buttons & PAD_DOWN)
                m_camera.updateTargetOffsets(0, 2);

            if(pad[0].buttons & PAD_LEFT)
                m_camera.updateTargetOffsets(-2, 0);

            if(pad[0].buttons & PAD_RIGHT)
                m_camera.updateTargetOffsets(2, 0);

            m_player.update();


            ReverseCorridorItter rit;

            for (rit = m_map.rbegin(); rit != m_map.rend(); rit++)
                (*rit)->update();
        }


        void draw() // const // EH!!! wtf ReverseIter isn't a member
        {
            m_player.draw();


            ReverseCorridorItter rit;

            for (rit = m_map.rbegin(); rit != m_map.rend(); rit++)
                (*rit)->draw();

        }


        Camera& getLevelCamera() {
            return m_camera;
        }

    };
}

#endif

The pointer is being set as far as I can tell, but when I try to access a function from Level, BOOM!

据我所知,指针正在设置,但是当我尝试从 Level 访问函数时,BOOM!

Thanks.

谢谢。

PS: The compiler is gcc 2.95.2 if that makes a difference.

PS:编译器是 gcc 2.95.2 如果这有所不同。

EDIT

编辑

Updated with complete code.

更新了完整的代码。

回答by John Dibling

You are #include-ing Level's complete declaration:

你是#include-ingLevel的完整声明:

#include <Level.hpp>

...and thenyou try to forward-declare Level:

...然后你尝试向前声明Level

namespace Game
{
    class Level;

Don't do this. Choose one or the other. (edit) Or at least put the forward-declaration before the #include-ion of the complete declaration. If all you're doing in game_corridor.hppis setting pointers to a Level, then a forward declare should do fine. If however you need to call functions on Levelfrom within the HPP file, then you'll need to #includethe complete declaration.

不要这样做。选择其中之一。(编辑) 或者至少将前向声明放在#include完整声明的-ion之前。如果您所做的game_corridor.hpp只是设置指向 a 的指针Level,那么前向声明应该没问题。但是,如果您需要Level从 HPP 文件中调用函数,则需要#include完整的声明。

EDIT2:

编辑2:

Based on your clarifying edit to your OP, you must#includethe complete declaration of Level, and not try to use a forward declaration.

根据您对 OP 的澄清编辑,您必须#include完整声明Level,而不是尝试使用前向声明。

回答by wilhelmtell

If you forward-declare Game::Levelthen don't #include it. In a not-so-related note, use #include "header.hpp", not #include <header.hpp>.

如果您提前声明,Game::Level则不要 #include 它。在不太相关的注释中,使用#include "header.hpp",而不是#include <header.hpp>

Editas per your updates: Bring the definition of Game::Corridor::update()outside the header and into an implementation file. This way the compile need not know anything about Game::Levelapart from the fact that it exists and it's a type.

根据您的更新进行编辑:将Game::Corridor::update()标题外部的定义带入实现文件中。这样,Game::Level除了它存在并且它是一种类型之外,编译不需要知道任何其他信息。

回答by Beta

The problem is that Corridor doesn't know what a Level is, because it can't really #include Level.hpp, because Level.hpp is what #included Corridor.hpp.

问题是Corridor 不知道Level 是什么,因为它不能真正#include Level.hpp,因为Level.hpp 就是#included Corridor.hpp。

The underlying problem is that you're trying to #include a source file. The reallyunderlying problem is that you're using #includewhen you haven't separated your code into source files and header files. Here's how to split it up. (I'm assuming you're familiar with compiling source files into object files, then linking them into executables.)

潜在的问题是您正在尝试 #include 源文件。在真正的根本问题是,你使用#include的时候你有没有代码分离为源文件和头文件。这是拆分方法。(我假设您熟悉将源文件编译成目标文件,然后将它们链接成可执行文件。)

Corridor.hpp:

走廊.hpp:

#ifndef GAME_CORRIDOR_HPP
#define GAME_CORRIDOR_HPP

#include <Moot/Math.hpp>

#include <Level.hpp>

namespace Game
{
  class Level;

  class Corridor
  {
    static const unsigned int defaultLevelDepth = 800;

    Moot::Math::Vector3D wp1, wp2, wp3, wp4;
    Moot::Math::Vector2D sp1, sp2, sp3, sp4;

    Level * p_level;

  public:

    Corridor(Moot::Math::Vector3D setFirstPoint, Moot::Math::Vector3D setSecondPoint);

    void update();
    void draw();

    void setLevel(Level* setLevel);
  };
}

#endif

Corridor.cpp:

走廊.cpp:

#include "Corridor.hpp"

namespace Game
{
  Corridor::Corridor(Moot::Math::Vector3D setFirstPoint, Moot::Math::Vector3D setSecondPoint) 
  {
    wp1 = setFirstPoint;
    wp2 = setSecondPoint;
    wp3 = setFirstPoint;
    wp3.z += defaultLevelDepth;
    wp4 = setSecondPoint;
    wp4.z += defaultLevelDepth;
  }

  void Corridor::update() 
  {  
    sp1 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp1);
    sp2 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp2);
    sp3 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp3);
    sp4 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp4);
  }

  // and so on

}