2013-02-05 15 views
3

我试图建立一个基本的实体/对象管理系统,我有两个类,一个用于继承实体的基类,另一个用于管理和控制它们。如何定义循环依赖关系的C++类?

这是我想要使用的源代码:

#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内的阵列来解决,但有没有办法用一些棘手的类操作顺利做到这一点?

回答

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; 
} 
+0

哇,谢谢。我很高兴看到这些简单的答案。很好的例子。 – object

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之外,不需要知道任何其他信息)。 EFiteratorEFentity声明的顺序无关紧要;你可以很容易地反转他们是这样的:

#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() { 
    // ... 

直到你到达定义你需要有前面声明可用。

+0

谢谢,因为它表达了与以前的答案相同的点。 – object