前向声明和循环依赖

Ora*_*lar 8 c++ dependencies declaration circular-dependency forward

我有两个课程,实体和水平.两者都需要访问彼此的方法.因此,使用#include会产生循环依赖的问题.因此,为了避免这种情况,我尝试在Entity.h中转发声明Level:

class Level { };
Run Code Online (Sandbox Code Playgroud)

但是,由于Entity需要访问Level中的方法,因此它无法访问此类方法,因为它不知道它们存在.有没有办法解决这个问题,而无需重新声明实体中的大部分级别?

Joh*_*ica 8

适当的前瞻性声明就是:

class Level;
Run Code Online (Sandbox Code Playgroud)

注意缺少花括号.这告诉编译器有一个名为的类Level,但没有关于它的内容.然后,您可以自由地将指针(Level *)和引用(Level &)用于此未定义的类.

请注意,您无法直接实例化,Level因为编译器需要知道类的大小才能创建变量.

class Level;

class Entity
{
    Level &level;  // legal
    Level level;   // illegal
};
Run Code Online (Sandbox Code Playgroud)

为了能够LevelEntity方法中使用,理想情况下,您应该在单独的文件中定义 Level方法,.cpp并且只在标题中声明它们.将声明与定义分开是C++的最佳实践.

// entity.h

class Level;

class Entity
{
    void changeLevel(Level &);
};


// entity.cpp

#include "level.h"
#include "entity.h"

void Entity::changeLevel(Level &level)
{
    level.loadEntity(*this);
}
Run Code Online (Sandbox Code Playgroud)

  • 编辑:我必须在entity.cpp中#include“ level.h”。我想出了是否不能将它包含在entity.h文件中,出于相同的原因,它也不能包含在.cpp文件中。包括此问题已解决。谢谢! (2认同)

Dor*_*don 1

你有两个选择:

  1. 使用指针在这种情况下你的前向声明应该没问题。
  2. 内联一个类的方法,在这种情况下,如果包含 .h 文件,则可以使用另一个类的方法。

就我个人而言,我会选择第 1 条路径,它更干净并且可以更好地访问。我使用了很多shared_ptr,所以我不必担心删除......

Entity.h:
class Level;
class Entity {

private:
   Level* m_pLevel;

public:
   bool  CheckLevel ();
   bool WasItThere();


Level.h

class Entity;
class Level {

private:
   Entity* m_pEntity;



    public:
       public bool CheckMyStuff();
       public bool CheckItOut() { return m_pEntity->WasItThere();}
}


Entity.cpp

#include "Level.h"

bool Entity::CheckLevel () {
  return true;
}


bool Entity::CheckLevel() {
   return m_pLevel->CheckMyStuff();
}

bool Entity::WasItThere() {
   return true;
}



Level.cpp

bool Level::CheckMyStuff() { 
    return true;
}

bool Level::CheckItOut() { 
    return m_pEntity->WasItThere();
}
Run Code Online (Sandbox Code Playgroud)