59

请问您对如何避免头文件的循环依赖有什么好的建议吗?

当然,从一开始,我就尝试将项目设计得尽可能透明。然而,随着越来越多的特性和类被添加,项目变得越来越不透明,循环依赖开始发生。

是否有任何通用的、经过验证的和工作的规则?谢谢。

4

8 回答 8

59

如果你有循环依赖,那么你做错了什么。

例如:

foo.h
-----
class foo {
public:
   bar b;
};

bar.h
-----
class bar {
public:
   foo f;
};

您可能想要的是非法的:

foo.h
-----
class bar; // forward declaration
class foo {
   ...
   bar *b;
   ...
};

bar.h
-----
class foo; // forward declaration
class bar {
   ...
   foo *f;
   ...
};

这没关系。

一般规则:

  1. 确保每个标题都可以单独包含。
  2. 如果您可以使用前向声明,请使用它们!
于 2011-01-27T13:13:35.163 回答
20
  • 尽可能使用前向声明。
  • 如果只有 cpp 文件需要,则将任何头包含从头文件中移出并放入相应的 cpp 文件中。执行此操作的最简单方法是将#include "myclass.h"第一个包含在myclass.cpp.
  • 在不同类之间的交互点引入接口可以帮助减少依赖关系。
于 2011-01-27T13:41:19.567 回答
9

我遵循的一些避免循环依赖的最佳实践是,

  1. 坚持 OOAD 原则。不要包含头文件,除非包含的类与当前类有组合关系。改用前向声明。
  2. 设计抽象类作为两个类的接口。通过该接口进行类的交互。
于 2011-01-27T14:00:19.290 回答
7

一般的方法是将共性分解到第三个头文件中,然后由两个原始头文件引用。

另请参阅循环依赖最佳实践

于 2011-01-27T13:10:29.333 回答
4

取决于您的预处理器功能:

#pragma once

或者

#ifndef MY_HEADER_H
#define MY_HEADER_H
your header file
#endif

如果你觉得设计头文件很无聊,那么你可能会对来自 Hwaci(SQLite 和化石 DVCS 的设计者)的 makeheaders 感兴趣。

于 2011-01-27T13:10:18.663 回答
4

您的目标是分层方法。您可以定义模块可以依赖于较低层模块的层,但应该使用观察者来完成相反的操作。现在你仍然可以定义你的层应该有多细,以及你是否接受层内的循环依赖,但在这种情况下我会使用this

于 2011-01-27T13:40:25.057 回答
3

一般来说,头文件应尽可能前向声明而不是包含其他头文件。

还要确保每个标题坚持一个类。

那么你几乎肯定不会出错。

最糟糕的耦合通常来自臃肿的模板代码。因为你必须在头文件中包含定义,这通常会导致必须包含各种头文件,然后使用模板的类包含模板头,包括大量其他内容。

出于这个原因,我通常会说:小心使用模板!理想情况下,模板不应该在其实现代码中包含任何内容。

于 2011-01-27T13:58:52.120 回答
2

Altough Artyom 提供了最佳答案,本教程也很棒,并提供了一些扩展http://www.cplusplus.com/forum/articles/10627/

于 2013-04-17T10:53:03.200 回答