C++ 避免头文件的循环依赖

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4816698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:38:12  来源:igfitidea点击:

Avoiding Circular Dependencies of header files

c++software-designarchitecture

提问by Bunkai.Satori

Do you have any good advice on how to avoid circular dependencies of header files, please?

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

Of course, from the beginning, I try to design the project as transparent as possible. However, as more and more features and classes are added, and the project gets less transparent, circular dependencies start happening.

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

Are there any general, verified, and working rules?Thanks.

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

采纳答案by Artyom

If you have circular dependency then you doing something wrong.

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

As for example:

例如:

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

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

Is illegal you probably want:

您可能想要的非法行为:

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

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

And this is ok.

这没关系。

General rules:

通用规则:

  1. Make sure each header can be included on its own.
  2. If you can use forward declarations use them!
  1. 确保每个标题都可以单独包含。
  2. 如果您可以使用前向声明,请使用它们!

回答by jon-hanson

  • Use forward declarations where possible.
  • Move any header includes out of a header file and into the corresponding cpp file if they are only needed by the cpp file. Easiest way to enforce this is to make the #include "myclass.h"the first include in myclass.cpp.
  • Introducing interfaces at the point of interaction between separate classes can help reduce dependencies.
  • 尽可能使用前向声明。
  • 如果仅 cpp 文件需要它们,则将任何头包含从头文件中移到相应的 cpp 文件中。执行此操作的最简单方法是#include "myclass.h"将第一个包含在myclass.cpp.
  • 在不同类之间的交互点引入接口可以帮助减少依赖性。

回答by Sulla

Some best practices I follow to avoid circular dependencies are,

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

  1. Stick to OOAD principles. Don't include a header file, unless the class included is in composition relationship with the current class. Use forward declaration instead.
  2. Design abstract classes to act as interfaces for two classes. Make the interaction of the classes through that interface.
  1. 坚持OOAD原则。不要包含头文件,除非包含的类与当前类有组合关系。请改用前向声明。
  2. 设计抽象类以充当两个类的接口。通过该接口进行类的交互。

回答by Ed Guiness

A general approach is to factor out the commonalities into a third header file which is then referenced by the two original header files.

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

See also Circular Dependency Best Practice

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

回答by Benoit

depending on your preprocessor capabilities:

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

#pragma once

or

或者

#ifndef MY_HEADER_H
#define MY_HEADER_H
your header file
#endif

If you find it very boring to design header files maybe makeheadersfrom Hwaci (designers of SQLite and fossil DVCS) could be of interest for you.

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

回答by stefaanv

What you're aiming at is a layered approach. You can define layers where modules can depend on lower layer modules but the inverse should be done with observers. Now you can still define how fine-grained your layers should be and whether you accept circular dependency within layers, but in this case I would use this.

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

回答by CashCow

In general header files should forwardly declare rather than include other headers wherever possible.

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

Also ensure you stick to one class per header.

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

Then you almost certainly will not go wrong.

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

The worst coupling usually comes from bloated template code. Because you have to include the definition inside the header, it often leads to all kinds headers having to be included, and then the class that uses the template includes the template header, including a load of other stuff.

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

For this reason, I would generally say: be careful with templates! Ideally a template should not have to include anything in its implementation code.

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

回答by rank1

Altough Artyom provided best answer this tutorial is also great and provides some extenstions http://www.cplusplus.com/forum/articles/10627/

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