3

我正在尝试建立一个基本的实体/对象管理系统,我有两个类,一个是要继承的实体的基类,另一个是管理和控制它们。

这是我正在尝试使用的源代码:

#include <iostream>
#define MAX_ENTS 400
class EFentity;
class EFiterator;
class EFentity {
     public:
          EFentity();
          virtual bool step();
          virtual void create(EFiterator*,int);
          virtual void destroy();
     private:
          int holder_id;
          EFiterator* holder;
};
EFentity::EFentity(void) {
     //    add base entity stuff
}
void EFentity::destroy() {
     holder->ents[holder_id]=NULL;
     std::cout << "destroying object id "<<holder_id;
     delete this;
}
void EFentity::create(EFiterator* h,int pos) {
     holder=h;
     holder_id=pos;
}
bool EFentity::step() {
     return false;
}
class EFiterator {
public:
     EFentity* ents[MAX_ENTS];
     int e_size;
     EFiterator();
     void push(EFentity* e);
     void update();
};
EFiterator::EFiterator() {
     e_size=0;
}
void EFiterator::update() {
     for(int i=0;i<e_size;i++) {
          if (!ents[i]->step()) {
               std::cout << "entity id "<< i<<" generated a fault!\n";
          } else std::cout << "entity id "<<i<<" passed step test.\n";
     }
}
void EFiterator::push(EFentity* e) {
     ents[e_size]=e;
     e->create(this,e_size++);
}
int main() {
     EFiterator main_iterator;
     main_iterator.push(new EFentity());
     main_iterator.update();
     std::cin.get();
     return 0;
}

此代码显然无法编译,以下是错误:

In member function `virtual void EFentity::destroy()':

[20] invalid use of undefined type `struct EFiterator' 
[5] forward declaration of `struct EFiterator'

我之前在 SO 上看到过这样的问题,但它们不需要访问其他类的成员变量和函数,因此可以通过指针轻松解决。

认为这可以通过使用原型函数来访问内部的数组来解决EFiterator,但是有没有办法通过一些棘手的类操作来顺利地做到这一点?

4

2 回答 2

3

EFentity::destroy()需要知道EFiterator调用时的具体类型

 holder->ents[holder_id]=NULL;

放在EFentity::destroy()后面EFiterator定义应该可以解决问题,例如放在后面EFiterator

void EFiterator::push(EFentity* e) {
     ents[e_size]=e;
     e->create(this,e_size++);
}

void EFentity::destroy() {
     holder->ents[holder_id]=NULL;
     std::cout << "destroying object id "<<holder_id;
     delete this;
}

通常在头文件中转发声明类型并在文件中包含具体类型.cpp,这会破坏circular include问题。

EFentity.h

class EFiterator;
class EFentity {
     public:
          EFentity();
          virtual bool step();
          virtual void create(EFiterator*,int);
          virtual void destroy();
     private:
          int holder_id;
          EFiterator* holder;
};

EFentity.cpp

#include "EFiterator.h"

EFentity::EFentity(void) {
     //    add base entity stuff
}
void EFentity::destroy() {
     holder->ents[holder_id]=NULL;
     std::cout << "destroying object id "<<holder_id;
     delete this;
}
void EFentity::create(EFiterator* h,int pos) {
     holder=h;
     holder_id=pos;
}
bool EFentity::step() {
     return false;
}
于 2013-02-05T00:55:17.227 回答
1

问题是您已经前向声明了类型EFIterator,然后尝试在编译器可见定义之前访问其成员。当编译器读取 的定义时EFentity::destroy(),它需要知道EFIterator有一个名为 的成员ents

解决方案很容易实现:将两个声明放在定义之前,如下所示:

#include <iostream>
#define MAX_ENTS 400
class EFentity;
// Now we can refer to EFentity by pointer or reference.

class EFiterator {
public:
  EFentity* ents[MAX_ENTS];
  int e_size;
  EFiterator();
  void push(EFentity* e);
  void update();
};
// Now we can refer to EFiterator by pointer, reference, or value.

class EFentity {
public:
  EFentity();
  virtual bool step();
  virtual void create(EFiterator*,int);
  virtual void destroy();
private:
  int holder_id;
  EFiterator* holder;
};
// Now we can refer to EFentity by pointer, reference, or value.

EFiterator::EFiterator() {
  // ...

现在声明EFiterator可以将类型引用EFentity为指针(除了它是 UDT 之外不需要知道任何其他内容),并且声明EFentity可以将类型引用EFiterator为指针(也不需要知道除EFiteratorUDT 之外的任何内容) . EFiterator和声明的顺序EFentity无关紧要;您可以像这样轻松地反转它们:

#include <iostream>
#define MAX_ENTS 400
class EFiterator;
// Now we can refer to EFiterator by pointer or reference.

class EFentity {
public:
  EFentity();
  virtual bool step();
  virtual void create(EFiterator*, int);
  virtual void destroy();
private:
  int holder_id;
  EFiterator* holder;
};
// Now we can refer to EFentity by pointer, reference, or value.

class EFiterator {
public:
  EFentity* ents[MAX_ENTS];
  int e_size;
  EFiterator();
  void push(EFentity*);
  void update();
};
// Now we can refer to EFiterator by pointer, reference, or value.

EFiterator::EFiterator() {
  // ...

直到你得到定义,你才需要前面的声明可用。

于 2013-02-05T01:05:51.850 回答