我正在尝试建立一个基本的实体/对象管理系统,我有两个类,一个是继承实体的基类,另一个是管理和控制它们。
这是我正在尝试使用的源代码:
#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上看到过这样的问题,但它们不需要访问其他类的成员变量和函数,所以可以用指针轻松解决。
我认为这可以通过使用prototyped函数来访问EFiterator
内部的数组来解决,但是有没有办法通过一些棘手的类操作顺利完成这个?
答案 0 :(得分: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;
}
答案 1 :(得分: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
作为指针(也不需要知道除EFiterator
以外的任何东西是UDT)。 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() {
// ...
在您进入定义之前,您需要提供前面的声明。