c++ - 如何识别 C++ 中循环依赖的来源

标签 c++

谁能告诉我如何确定哪些类导致了我所看到的循环依赖问题?

最佳答案

在这种情况下会出现循环依赖的典型问题:

// foo.h
#ifndef FOO_H
#define FOO_H

#include "bar.h"

struct Foo { void use(Bar); };

#endif // FOO_H

// bar.h
#ifndef BAR_H
#define BAR_H

#include "foo.h"

struct Bar { void use(Foo); };

#endif // BAR_H

// bar.cpp
#include "bar.h"

当预处理器处理 bar.cpp 时会发生以下情况:

// bar.cpp

// #include "bar.h"
// BAR_H is not defined
// #define BAR_H

// #include "foo.h"
// FOO_H is not defined
// #define FOO_H

// #include "bar.h"
// BAR_H is defined, skip
// #endinclude "bar.h"

struct Foo { void use(Bar); }; // ERROR: Bar is not defined

// #endinclude "foo.h"

struct Bar { void use(Foo); }; // OK: Foo is defined

// #endinclude "bar.h"

这可能会使用预处理器技巧检测到,以便在编译时显示一个很好的消息。然而,它有点复杂,并且增加了已经必要的包含保护程序......所以大多数时候,你只是尝试编译,如果它没有,并且你无法理解错误,你总是可以得到使用编译器开关(在 gcc 上为 -E)的预处理文件。

现在,进入预处理器技巧。我们可以看到的问题是,即使定义了 BAR_H,该文件还没有被包含在内。

解决方案是准备另一个守卫,以表明整个文件已被处理的事实,并在我们处于仅定义两个守卫之一的情况下发出错误。

看起来是这样的:

// bar.h
#ifdef BAR_H
#ifndef BAR_H_2
# error "Cyclic inclusion involving bar.h"
#endif // BAR_H_2
#else

#include "foo.h"

struct Bar { void use(Foo); };

#define BAR_H_2
#endif // BAR_H

不过如您所见,对于相对较低的频率错误,它使头部防护装置已经需要的麻烦增加了一倍。所以它通常被认为不值得。

关于c++ - 如何识别 C++ 中循环依赖的来源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5700393/

相关文章:

c++ - 我应该只为一个电话在免费商店上创建对象吗?

c++ - 哪些因素使迭代器在 Debug模式下如此缓慢(VC++ 2012)

c++ - 奇怪的 "Undefined symbols"错误?

c++ - 在 GLUT 中绘制字符串

c++ - 转换数据包数据的 Python 和 C++ 套接字

c++ - 将 vector <int> 转换为字符串

c++ - 使用 boost::lambda::bind 的任意函数调用?

c++ - DLL 执行程序中的环境路径

c++ - WinHttpGetDefaultProxyConfiguration 返回错误的代理信息

c++ - C++ 中的复数或单数命名空间名称