C ++中的递归头部包含错误

时间:2014-11-20 01:50:03

标签: c++ header include

我使用两个相互依赖的类。但是,当我编译程序时,我得到一个荒谬的异常描述。只有在World.h头文件中包含Creature头文件时,我才减少了代码以显示错误。在有机会实现前向声明或模板之前抛出异常。此外,预处理器指令在我的情况下不起作用。

生物标题:

#ifndef __CREATURE_H
#define __CREATURE_H
#include "World.h"
    class Creature
    {
    public:
        //World *world; -- This class only needs a pointer to world. 
    };
#endif

世界标题:

#ifndef WORLD_H
#define WORLD_H
#include "Creature.h"
    class World
    {
    public:
        Creature** world;
    };
#endif

完成示例的驱动程序:

#include "World.h"
int main()
{
    World world;
    return 0;
}

Visual Studio 2012的例外消息:

world.h(14): error C2143: syntax error : missing ';' before '*'
world.h(14): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

我在最小的例子中注意到Intellisense会强调包含和悬停显示:"包含文件..包含自身"。这在我的大项目中并没有发生。但是,注释include,取消注释另一个类的实例化,然后编译项目会产生相同的错误。

4 个答案:

答案 0 :(得分:1)

问题是编译器在看到class Creature之前“看到”World*,并在其World之前完成。如果我们手工执行#include,这就变得很明显了:

#ifndef WORLD_H
#define WORLD_H

   //#include "Creature.h"
      #ifndef __CREATURE_H
      #define __CREATURE_H
      #include "World.h" // the #ifndef prevents this from expanding into anything interesting
      class Creature
      {
      public:
         World *world; // here's World! Except...it hasn't been declared or defined yet. 
      };
      #endif

   // finally we get to class World, but it's too late     
   class World
   {
   public:
      Creature** world;
   };
#endif

一个简单的解决方案是转发声明World而不是使用倒数包含。 e.g:

#ifndef __CREATURE_H
#define __CREATURE_H
    class World; // instead of #include "World.h"

    class Creature
    {
    public:
        World *world;
    };
#endif

根据您显示的代码,您可以在world.h中使用Creature执行相同的操作(尽管您只需要其中一个来解决编译问题)。

答案 1 :(得分:0)

使用前瞻声明。

在Creature.h中更改

#include "World.h"

class World;

答案 2 :(得分:0)

我认为这是一个声明问题。在你的头文件中加上“#include”并不是一个好主意。

更好的方法:(注意我使用“#pragma once”而不是“#ifndef #define”)

Creature.h

#pragma once
class World;
class Creature {.........}

World.h

#pragma once
class Creature;
class World {..........}

你的任何.cpp文件

#include "World.h"
#include "Creature.h"

答案 3 :(得分:0)

我建议将预处理器输出发送到文件,并检查实际预处理代码的样子。

要解决这样的问题,我会创建另一个带有前向声明的头文件(例如declarations.h),然后在定义类实现的每个头中包含前向声明。

保持标题不被包含多次(#ifndef#pragma once等)的常规方法可以完美地工作,以防止任何事情被多次声明或定义,同时允许两个世界和生物用指针互相引用。

这里的关键是,定义main函数的cpp文件需要包括World.hCreature.h