C++ 避免头文件的循环依赖关系
关于如何避免头文件的循环依赖,您有什么好的建议吗 当然,从一开始,我就尝试将项目设计得尽可能透明。然而,随着越来越多的特性和类被添加,项目变得不那么透明,循环依赖开始发生C++ 避免头文件的循环依赖关系,c++,software-design,architecture,C++,Software Design,Architecture,关于如何避免头文件的循环依赖,您有什么好的建议吗 当然,从一开始,我就尝试将项目设计得尽可能透明。然而,随着越来越多的特性和类被添加,项目变得不那么透明,循环依赖开始发生 是否有任何通用的、经过验证的和有效的规则?谢谢。取决于您的预处理器功能: #pragma once 或 如果您觉得设计头文件非常枯燥,那么您可能会对来自Hwaci(SQLite和fossil DVCS的设计者)的头文件感兴趣。一般的方法是将通用性分解到第三个头文件中,然后由两个原始头文件引用 另请参见如果存在循环依赖,则说明
是否有任何通用的、经过验证的和有效的规则?谢谢。取决于您的预处理器功能:
#pragma once
或
如果您觉得设计头文件非常枯燥,那么您可能会对来自Hwaci(SQLite和fossil DVCS的设计者)的头文件感兴趣。一般的方法是将通用性分解到第三个头文件中,然后由两个原始头文件引用
另请参见如果存在循环依赖,则说明您做错了什么 例如:
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;
...
};
这没关系
一般规则:
你的目标是一个。您可以定义模块可以依赖于较低层模块的层,但应使用进行反向定义。现在,您仍然可以定义层的细粒度以及是否接受层内的循环依赖关系,但在本例中,我将使用。
- 尽可能使用转发声明
- 如果cpp文件只需要任何头包含,则将其从头文件移出并移入相应的cpp文件。最简单的方法是将
作为#include“myclass.h”
中的第一个includemyclass.cpp
- 在独立类之间的交互点引入接口有助于减少依赖性
出于这个原因,我通常会说:小心使用模板!理想情况下,模板不必在其实现代码中包含任何内容。我为避免循环依赖性而遵循的一些最佳实践是
尽管Artyom提供了最佳答案,但本教程也很棒,并提供了一些扩展这与其说是为了避免循环依赖,不如说是为了避免“重新定义符号”错误。这是一个标准的,绝对需要的练习。你好,贝诺德,是的,我同意彼得·托洛克的观点。这在每本教科书和一个必须使用的实践中都有解释。非常感谢您的回复。+1嗨,阿蒂奥姆,谢谢您的回复。更频繁地使用转发声明可能会有所帮助。@Artyom:如果指针是用来拥有资源的,我建议使用
作用域\u ptr
或唯一\u ptr
。如果指针仅仅是一个对象的引用,那么可能有必要使用观察者模式,以便在被引用对象被销毁时它“未设置”。@Matthieu M.当然,(或者auto\u ptr
,当您不想依赖boost
或C++0x
时,这会更好)。但我更想展示总体思路,而不是现场代码。它甚至可能是std::vector
,如果foo有前向声明,它会起作用。@Artyom:不,不要使用auto\u ptr
,它更糟糕。如果需要,可以从boost中删除作用域ptr
的代码,但是自动ptr
会带来太多惊喜(在复制/分配时)。但是如果我们使用*b指针的某些方法?那么我们就不能把它包括进去。那怎么办呢?这里展示了我们可以内联这些函数,但它看起来不像是一个好的通用方法+1hi-Ed,这是另一个非常好的建议。谢谢。我查看了你提供的链接,它显示了重新设计分类以避免循环依赖的好例子。+1你好,Jon,谢谢你的回复。上面已经提到了你的一些建议,但是,始终将heade文件包含到.cpp文件中而不是.h文件中的方法是新的和有用的。我认为这个答案更好地解决了如何避免循环依赖的编译错误的问题,同时避免了因为必须处理循环依赖而犯错误的咒语。如果您使用的是GoF设计模式和复杂性,那么在某一点上您将具有循环依赖性。最好的建议不仅仅是前瞻性声明(这过于简化了解决方案),而是要点2。第二个建议是我一直在寻找的+1 hello Stefaanv,分层方法对我来说非常新,看起来需要大量准备和重新设计。这是非常有价值的建议。谢谢。分层方法是一个很好的想法,特别是因为它不是C++特定的,因此在很多情况下都是有价值的:+ 1 Arun,尤其是使用抽象/接口类的第二个建议是有用的。我要试一试。谢谢。+1嗨,现金牛,老实说,我没有太注意转发声明。相反,我使用了“包含”。非常感谢你的回答。
foo.h
-----
class bar; // forward declaration
class foo {
...
bar *b;
...
};
bar.h
-----
class foo; // forward declaration
class bar {
...
foo *f;
...
};