0

我正在为一个小 2D 游戏设置一些框架。现在,我只有几个类,但我立即陷入编译器问题。

我只用main函数运行了这个程序,所以我可以确认 Allegro(图形库)库链接已经工作。

我已将所有头文件 (.h) 放在解决方案资源管理器的“头文件”部分下,并将所有源文件 (.cpp) 放在“源文件”部分中。根据这个 Allegro 教程,我只修改了默认设置:http ://wiki.allegro.cc/index.php?title=Windows,_Visual_Studio_2010_and_Allegro_5 。它不应该以破坏性的方式影响任何事情。

我有几个文件,所以我将列出每个文件。我将跳过一些代码以减少大小和冗余。当我省略任何代码或不逐字地做任何事情时,我会在代码中写上这样的注释。(编辑:我实际上没有跳过任何代码)

主文件

#include "common.h"

int main(int argc, char **argv)
{
   ALLEGRO_DISPLAY *display = NULL;
   World* world = new World(640, 480);

   if(!al_init()) {
      fprintf(stderr, "failed to initialize allegro!\n");
      return -1;
   }

   display = al_create_display(640, 480);
   if(!display) {
      fprintf(stderr, "failed to create display!\n");
      return -1;
   }

   al_clear_to_color(al_map_rgb(0,0,0));

   world->draw(display);

   al_flip_display();

   al_rest(10.0);

   al_destroy_display(display);

   return 0;
}

常见的.h

#if !defined(COMMON_INC)
#define COMMON_INC

#include "World.h"
#include "Pane.h"
#include <stdio.h>
#include <allegro5/allegro.h>

#endif

世界.h

#if !defined(WORLD_INC)
#define WORLD_INC

#include "common.h"
#include "Pane.h"

class World{
public:
    World(int wp, int hp);
    void draw(ALLEGRO_DISPLAY* display);
    void update();


protected:

private:
    Pane* panel;
    int heightPix, widthPix;

};

#endif

世界.cpp

#include "common.h"

World::World(int wp, int hp){
    widthPix = wp;
    heightPix = hp;
    panel = new Pane(this, 10, 10, 300, 400);
    return;
}

void World::draw(ALLEGRO_DISPLAY* display){
    panel->draw(display);
    return;
}

窗格.h

#if !defined(PANE_INC)
#define PANE_INC

#include "common.h"

class Pane{
public:
    Pane(World* w, int xv, int yv, int wi, int he);
    World* getWorld();
    int getZ();
    void draw(ALLEGRO_DISPLAY* display);
    ALLEGRO_BITMAP* getBackground();

protected:
    void setXY(int xv, int yv);
    void setWidthHeight(int wi, int he);
    void setZ(int zv);
    void setBackground(ALLEGRO_BITMAP* ba);

private:
    int z;
    int x, y; //pixels
    int width, height; //pixels
    World* world;
    ALLEGRO_BITMAP* background;
};

#endif

窗格.cpp

#include "common.h"

Pane::Pane(World* w, int xv, int yv, int wi, int he){
    this->setWidthHeight(wi, he);
    this->setXY(xv, yv);
    this->world = w;
}

World* Pane::getWorld(){
    return world;
}

void Pane::setXY(int xv, int yv){
    x = xv;
    y = yv;
    return;
}

void Pane::setWidthHeight(int wi, int he){\
    width = wi;
    height = he;
    return;
}

void Pane::setZ(int zv){
    z = zv;
    return;
}

void Pane::draw(ALLEGRO_DISPLAY* display){
    if(background != NULL)
        al_draw_bitmap(background, x, y, 0);
    else{
        background = al_create_bitmap(width, height);

        al_set_target_bitmap(background);

        al_clear_to_color(al_map_rgb(255, 0, 255));

        al_set_target_bitmap(al_get_backbuffer(display));

        al_draw_bitmap(background, x, y, 0);
    }
    return;
}

编译器在构建时会生成此错误报告:(我称这款游戏为 madscientist,因为它应该是炼金术主题的)

1>------ Build started: Project: MadScientist, Configuration: Debug Win32 ------
1>  main.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(8): error C2061: syntax error : identifier 'World'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): warning C4183: 'getWorld': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(11): error C2061: syntax error : identifier 'ALLEGRO_DISPLAY'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): warning C4183: 'getBackground': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(18): error C2061: syntax error : identifier 'ALLEGRO_BITMAP'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(24): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(24): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(10): error C2061: syntax error : identifier 'ALLEGRO_DISPLAY'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\main.cpp(22): error C2660: 'World::draw' : function does not take 1 arguments
1>  World.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(8): error C2061: syntax error : identifier 'World'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): warning C4183: 'getWorld': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(11): error C2061: syntax error : identifier 'ALLEGRO_DISPLAY'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): warning C4183: 'getBackground': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(18): error C2061: syntax error : identifier 'ALLEGRO_BITMAP'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(24): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(24): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(10): error C2061: syntax error : identifier 'ALLEGRO_DISPLAY'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.cpp(6): error C2661: 'Pane::Pane' : no overloaded function takes 5 arguments
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.cpp(10): error C2511: 'void World::draw(ALLEGRO_DISPLAY *)' : overloaded member function not found in 'World'
1>          c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(7) : see declaration of 'World'
1>  Pane.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(8): error C2061: syntax error : identifier 'World'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): warning C4183: 'getWorld': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(11): error C2061: syntax error : identifier 'ALLEGRO_DISPLAY'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): warning C4183: 'getBackground': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(18): error C2061: syntax error : identifier 'ALLEGRO_BITMAP'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(24): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(24): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(10): error C2061: syntax error : identifier 'ALLEGRO_DISPLAY'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.cpp(3): error C2511: 'Pane::Pane(World *,int,int,int,int)' : overloaded member function not found in 'Pane'
1>          c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(6) : see declaration of 'Pane'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.cpp(9): error C2556: 'World *Pane::getWorld(void)' : overloaded function differs only by return type from 'int *Pane::getWorld(void)'
1>          c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9) : see declaration of 'Pane::getWorld'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.cpp(9): error C2371: 'Pane::getWorld' : redefinition; different basic types
1>          c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9) : see declaration of 'Pane::getWorld'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.cpp(10): error C2065: 'world' : undeclared identifier
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.cpp(30): error C2511: 'void Pane::draw(ALLEGRO_DISPLAY *)' : overloaded member function not found in 'Pane'
1>          c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(6) : see declaration of 'Pane'
1>  Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

你拥有我所做的所有信息。我会为你总结一下,省去翻遍所有东西的麻烦。

  • 有分为头接口和源实现的类
  • common.h 包含在所有文件中。它本身包括其他头文件中的所有类定义
  • 编译时,编译器不会将其他头文件中定义的类识别为数据类型。正如您所料,错误会级联。
  • 实时错误检查器不会记录任何错误。例如,当将“世界”用作数据类型时,将鼠标悬停在“世界”一词上时Pane,它可以完美地识别该类型。实时错误检查器是在编译时间之前用红色下划线错误的功能。
  • 除了前面提到的修改之外,这个 Visual Studio 2012 Express 是新的。该项目被创建为一个空的 C++ 项目。在添加许多头文件和源代码之前,该main函数已正确编译。

感谢您的任何回复。如果您有任何疑问,请询问。我在使用 Visual Studio 时遇到的问题总是让我感到厌烦。

编辑:

我的循环标头逻辑由标头守卫保护。我不认为这种冗余是一个问题。

我尝试从头文件中删除所有包含,除了 Allegro 库的包含。这似乎效果更好,但仍然存在奇怪的问题。为什么包含的行为会导致这些数据类型出错仍然是一个谜。这是新的错误日志:

1>------ Build started: Project: MadScientist, Configuration: Debug Win32 ------
1>  main.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>  World.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.cpp(6): error C2065: 'panel' : undeclared identifier
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.cpp(11): error C2065: 'panel' : undeclared identifier
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.cpp(11): error C2227: left of '->draw' must point to class/struct/union/generic type
1>          type is ''unknown-type''
1>  Pane.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>  Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

编辑第 2 轮:

我切换了我的代码,所以 common.h 只包含 stdio 和 Allegro。所有的头文件和源文件都包括 common.h 和它们单独使用的任何类的头文件。Pane.cpp 包括 Pane.h 和 common.h。World.h 包括 Pane.h 和 common.h。

错误日志显示:

1>------ Build started: Project: MadScientist, Configuration: Debug Win32 ------
1>  main.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C2061: syntax error : identifier 'World'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(10): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(10): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(10): warning C4183: 'getWorld': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>  World.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C2061: syntax error : identifier 'World'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(10): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(10): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(10): warning C4183: 'getWorld': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.cpp(7): error C2661: 'Pane::Pane' : no overloaded function takes 5 arguments
1>  Pane.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>  Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

这就是我现在看到我的包含订单的方式:

  1. 主要包括常见的
  2. 通用定义 COMMON_INC
  3. 常见的包括 stdio 和 allegro
  4. 主要包括 World.h
  5. 世界定义 WORLD_INC
  6. 世界包括共同,被封锁。但这应该没问题,因为 common 已经包含在内
  7. 世界包括窗格
  8. 窗格定义 PANE_INC
  9. 窗格包括公用,它被阻止。但这应该没问题,因为 common 已经包含在内。
  10. 窗格包括世界。这被阻止了,因为 main 已经包含了 World。这不应该没问题,因为 World 已经包含在内。如果我需要多次包含文件,为什么我还要有编译器保护,每个使用它的文件一次?

编辑第 3 轮: 我从这里的答案和评论中学到了很多东西。事实证明,根据维基百科,“循环依赖通常是由需要实现某种回调功能的缺乏经验的程序员引入的。” Pane 使用 World 和 World 使用 Pane 的事实本身就是一个设计缺陷。在 Java 中,这对我来说一切都很好。这很容易;我认为这是通知“拥有”对象动作的实体的最佳方式。

事实证明,这是一个糟糕的设计方案。对象不应依赖于它们的“拥有者”。相反,我需要实现一个观察者系统,窗格可以告诉世界它已经更新了它的状态。

阅读维基百科清除了我的所有问题,所以我现在认为这个问题已经完成。感谢贡献者为学习程序员提供的帮助。

4

2 回答 2

6

您的头文件可能无法正确链接。您以循环方式包含标题。您的头文件包括common.h,而common.h反过来又包括其他头文件,例如World.hPane.h

这是任何编译器都无法编译的。您必须开发标题的层次结构,从低级标题到高级标题,并确保较高级别的标题仅包含较低级别的标题。这样,您将确保没有圆形夹杂物。

无论如何,为什么你common.h包含World.hand Pane.h?这看起来像是一个明显的错误。common.h旨在成为低级标题。让World.hPane.h包含它,但不要包含World.hPane.h进入common.h.

请注意,在这种情况下,标头保护不能解决任何问题。他们只是确保包含周期不会变得无限。它们打破了循环,但它们不能帮助您解决声明之间的循环依赖关系(如果存在这种依赖关系)。

看看你的情况在处理时会发生什么main.cpp

  1. main.cpp包括common.h
  2. common.h定义COMMON_INC
  3. common.h包括World.h
  4. World.h定义WORLD_INC
  5. World.h包括common.h. 整个common.h被包含守卫跳过,因为COMMON_INC在步骤 2 中定义了。
  6. World.h包括Pane.h
  7. Pane.h定义PANE_INC
  8. Pane.h包括common.h. 整个common.h被包含守卫跳过,因为COMMON_INC在步骤 2 中定义了。
  9. Pane.h指类型World。类型World是未知的,因为我们还没有得到它的定义World.h错误!
于 2012-12-08T03:07:36.727 回答
1

如果您进行以下更改,我认为即使包含通告,所有内容都将编译

  1. common.h您需要重新排列标题的顺序。

    #include <allegro5/allegro.h>
    #include "World.h"
    #include "Pane.h"
    #include <stdio.h>
    
  2. pane.h之后#include common.h,添加一个前向声明class World

    #include "common.h"
    class World;
    class Pane{
     .....
    

我认为这将使您的错误消失或至少大大减少它们。我的答案是基于您提供的原始代码,而不是基于编辑。

于 2012-12-08T03:35:43.500 回答