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

Max*_*ahm 2 c++ header class 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_;
}
Run Code Online (Sandbox Code Playgroud)

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

// 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_;
}
Run Code Online (Sandbox Code Playgroud)

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

编辑

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

// facet.h
#include "point.h"
class Facet {
    ...
  private:
    Point normal_;
}
Run Code Online (Sandbox Code Playgroud)

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

Jos*_*eld 7

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

// model.h
class Facet;

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

// facet.h
class Model;

class Facet {
    ...
    Model *parent_;
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 我见过的这些非常常见的问题之一的最佳答案之一。 (2认同)