C ++中交叉依赖类的最佳实践

时间:2014-01-15 10:26:15

标签: c++ class header circular-dependency forward-declaration

我有两个相互依赖的类:

// model.h
#include "facet.h"
class Model {
    ...
    std::map<int, std::vector<Facet*> > enqueue_list_;
}

// facet.h
#include "model.h"
class Facet {
    ...
    Model *parent_;
}

在尝试编译时,编译器显然非常沮丧。我用这样的前向类声明修复了它:

// model.h
#include "facet.h"
class Facet;
class Model {
    ...
    std::map<int, std::vector<Facet*> > enqueue_list_;
}

// facet.h
#include "model.h"
class Model;
class Facet {
    ...
    Model *parent_;
}

但我不喜欢这样做。这对我来说似乎很麻烦,很难维护。我认为通过使用头文件开始解决这类问题。有没有更好的方法来解决我错过的问题?我喜欢不必在其他类头文件中转发声明类。我觉得我在这里缺少一些重要的东西。如果我仍然得到交叉依赖性投诉,那么头文件究竟有什么意义呢? 提前谢谢,
最大

修改

感谢您的快速回复。我接受了建议并删除了头文件中的包含,并完全切换到转发声明。我是正确的假设我仍然需要实际包含标头,如果类具有类似的直接类分配:

// facet.h
#include "point.h"
class Facet {
    ...
  private:
    Point normal_;
}

我在尝试使用前向声明时遇到错误。这确实是我必须#include的情况吗?

1 个答案:

答案 0 :(得分:7)

你根本不应该#include。由于您只存储指针,因此您不需要类的完整定义 - 您只需要声明。只需单独使用前向声明:

// model.h
class Facet;

class Model {
    ...
    std::map<int, std::vector<Facet*> > enqueue_list_;
}

// facet.h
class Model;

class Facet {
    ...
    Model *parent_;
}

头文件的要点是能够在多个翻译单元中重用函数和对象的声明以及类的定义。在这种情况下,您不需要类的定义,只需要声明。

正如您最初所做的那样,model.h将包含facet.hmodel.h包括facet.h ...这显然会导致无限递归包含。如果你的标题包含了守卫,那么无限递归就会被阻止,但其中一个类不会知道另一个。例如,如果首先对model.h进行预处理,则会facet.h包含Facet,并且能够查看facet.h的定义,但model.h将无法包括Model {{1}}(因为包含保护)因此它对{{1}}一无所知。