【问题标题】:Field Has Incomplete Type, Compiling From Multiple Files字段类型不完整,从多个文件编译
【发布时间】:2012-11-12 02:32:28
【问题描述】:

我正在尝试为基于代理的僵尸启示录模拟编译几个文件(太棒了,对吧!?)无论如何,我收到一个错误,我认为这与包含头文件的顺序有关,但我不知道如何弄清楚出了什么问题以及如何解决它。确切的错误是:“在 main.cpp 包含的文件中,‘位置’字段的类型不完整。”然后类似地,“在构造函数 Creature::Creature() 'Location' 中未声明”。

这是我的文件:

定义.h

#ifndef definitions_h
#define definitions_h
class Creature;
class Item;
class Coords;

class Grid
{

public:
      Creature*** cboard;
      Item*** iboard;

      Grid(int WIDTH, int HEIGHT);
      void FillGrid(int H, int Z); //initializes grid object with humans and zombies  
      void Refresh(); //calls Creature::Die(),Move(),Attack(),Breed() on every square
      void UpdateBuffer(char** buffer);
      bool isEmpty(int startx, int starty, int dir);

};

class Random
{
    public:
        int* rptr;
        void Print();
        Random(int MIN, int MAX, int LEN);
        ~Random();
    private:
        bool alreadyused(int checkthis, int len, int* rptr);
        bool isClean();
        int len;
};

class Creature
{

public:
      bool alive;
      Coords Location;
      char displayletter;

      Creature() {Location.x=0; Location.y=0;} //ERROR HERE
      Creature(int i, int j) {Location.xvalue(i); Location.yvalue(j);} 

      virtual void Attack();
      virtual void Breed();
      virtual void Move(Creature*** cboard);
      virtual void Die();

      virtual void MoveTo(Creature*** cboard, int dir); 
      virtual int DecideSquare(Creature*** cboard); 
};

class Human : public Creature 
{
public:      
      bool armed; //if armed, chances of winning fight increased for next fight 
      bool vaccinated; //if vaccinated, no chance of getting infected

      int bitecount; //if a human is bitten, bite count is set to a random number
      int breedcount; //if a human goes x steps without combat, will breed if next to a human
      int starvecount; //if a human does not eat in x steps, will die 

      void Attack(Creature*** cboard);
      void Breed(Creature*** cboard); //will breed after x steps and next to human
      void Move(Creature*** cboard); //moves and checks itemboard for food
      void Die(); //depends on bitecount, starvecount, and bool alive

      void MoveTo(Creature*** cboard, int dir);
      int DecideSquare(Creature*** cboard) {Creature::DecideSquare(Creature*** cboard);}

};

class Zombie : public Creature
{
   public:
      Zombie(int i, int j) {Creature::Creature()};
      void Attack(Creature*** cboard); //will attack any adjacent human
      void Breed() {} //does nothing
      void Move(Creature*** cboard) {Creature::Move(Creature*** cboard;}
      void Die(); //can only die from being attacked, never starves


};

class Item
{

};

class Coords
{
  public:   
      int x;
      int y;
      int MaxX;
      int MaxY;

      Coords() {x=0; y=0; MaxX=0; MaxY=0;}
      Coords(int X, int Y, int WIDTH, int HEIGHT) {x=X; y=Y; MaxX=WIDTH; MaxY=HEIGHT; }

      void MoveRight();
      void MoveLeft();
      void MoveUp();
      void MoveDown();
      void MoveUpRight();
      void MoveUpLeft();
      void MoveDownRight();
      void MoveDownLeft();
      void MoveDir(int dir);
      void setx(int X) {x=X;}
      void sety(int Y) {y=Y;}
};

#endif

main.cpp

#include <cstdlib>
#include <iostream>
#include "definitions.h"

using namespace std;

int main(int argc, char *argv[])
{
    system("PAUSE");
    return EXIT_SUCCESS;
}

定义.cpp

#include <cstdlib>
#include "definitions.h"

Grid::Grid(int WIDTH, int HEIGHT)
{
     //builds 2d array of creature pointers
     cboard = new Creature**[WIDTH];
     for(int i=0; i<WIDTH; i++)
     {
             cboard[i] = new Creature*[HEIGHT];
     }

     //builds 2d array of item pointers
     iboard = new Item**[WIDTH];
     for (int i=0; i<WIDTH; i++)
     {
              iboard[i] = new Item*[HEIGHT];
     }
}

void Grid::FillGrid()
{
     /* For each creature pointer in grid, randomly selects whether to initalize
     as zombie, human, or empty square. This methodology can be changed to initialize
     different creature types with different probabilities */

     int random;

     for (int i=0; i<WIDTH; i++)
     {
         for (int j=0; j<HEIGHT; j++)
         {
             Random X(1,100,1); //create a single random integer from [1,100] at X.rptr
             random=X->rptr;
             if (random < 20)
                cboard[i][j] = new Human(i,j);
             else if (random < 40) 
                  cboard[i][j] = new Zombie(i,j); 
             else 
                  cboard[i][j] = NULL;
         }
     } //at this point every creature pointer should be pointing to either
     //a zombie, human, or NULL with varying probabilities 

}

void Grid::UpdateBuffer(char** buffer)
{
     for (int i=0; i<WIDTH; i++)
     {
         for (int j=0; j<HEIGHT; j++)
         {
             if (cboard[i][j])
                buffer[i][j]=cboard[i][j]->displayletter;
             else
                 buffer[i][j]=' ';
         }
     }

}

bool Grid::isEmpty(int startx, int starty, int dir)
{
     Coords StartLocation(startx,starty,WIDTH,HEIGHT);
     switch(dir)
     {
                case 1:
                     StartLocation.MoveUp();
                      if (cboard[StartLocation.x][StartLocation.y])
                        return 0;
                case 2:
                     StartLocation.MoveUpRight();
                      if (cboard[StartLocation.x][StartLocation.y])
                        return 0;
                case 3:
                     StartLocation.MoveRight();
                      if (cboard[StartLocation.x][StartLocation.y])
                        return 0;
                case 4:
                     StartLocation.MoveDownRight();
                      if (cboard[StartLocation.x][StartLocation.y])
                        return 0;
                case 5:
                     StartLocation.MoveDown();
                      if (cboard[StartLocation.x][StartLocation.y])
                        return 0;
                case 6:
                     StartLocation.MoveDownLeft();
                      if (cboard[StartLocation.x][StartLocation.y])
                        return 0;
                case 7:
                     StartLocation.MoveLeft();
                      if (cboard[StartLocation.x][StartLocation.y])
                        return 0;
                case 8:
                     StartLocation.MoveUpLeft();
                      if (cboard[StartLocation.x][StartLocation.y])
                        return 0; 
     }
     return 1;
}


void Coords::MoveRight() {(x==MaxX)? (x=0):(x++);}
void Coords::MoveLeft() {(x==0)? (x=MaxX):(x--);}
void Coords::MoveUp() {(y==0)? (y=MaxY):(y--);}
void Coords::MoveDown() {(y==MaxY)? (y=0):(y++);} 
void Coords::MoveUpRight() {MoveUp(); MoveRight();}
void Coords::MoveUpLeft() {MoveUp(); MoveLeft();}
void Coords::MoveDownRight() {MoveDown(); MoveRight();}
void Coords::MoveDownLeft() {MoveDown(); MoveLeft();}
void Coords::MoveDir(int dir)
{
     switch(dir)
     {
                case 1:
                     MoveUp();
                     break;
                case 2:
                     MoveUpRight();
                     break;
                case 3:
                     MoveRight();
                     break;
                case 4:
                     MoveDownRight();
                     break;
                case 5:
                     MoveDown();
                     break;
                case 6:
                     MoveDownLeft();
                     break;
                case 7:
                     MoveLeft();
                     break;
                case 8:
                     MoveUpLeft();
                     break;
                case 0:
                     break;
     }
}

【问题讨论】:

    标签: c++ incomplete-type


    【解决方案1】:

    当一个变量被声明时,它的类型必须是已知的。在您的情况下,这意味着 Coords 的定义必须在声明 Coords Location; 中使用之前。

    从编译器的角度来看:它需要知道Location 将占用多少空间,为此它需要知道Coords 的定义。当然,它是从上到下解析的。

    【讨论】:

      【解决方案2】:

      您在definitions.h 中的class Coords 前向声明不足以声明Coords 类型的变量。

      前向声明引入了类型,但不完整。您可以使用指向不完整类型的指针声明变量,但不能声明具有不完整类型的变量。所以你必须把class Coords的定义移到class Creature的定义之前。

      如果发现自己有循环声明依赖,就必须引入指针或引用声明器来解决。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-10
        • 2011-04-29
        • 2017-08-16
        • 2013-11-25
        相关资源
        最近更新 更多