在 C 或 C++ 中处理循环依赖的最佳方法?
Best way to deal with cyclic dependancies in C or C++?
在 C 中,当我需要这个时:
文件a.h
:
#ifndef A_H
#define A_H
#include "b.h"
typedef struct A { B* second_struct; } A;
#endif /* !A_H */
文件b.h
:
#ifndef B_H
#define B_H
#include "a.h"
typedef struct B { A* first_struct; } B;
#endif /* !B_H */
我冒昧地以这种方式重新排列:
typedef struct A A;
#ifndef A_H
...
(b.h
也是如此)
我在 header 的第一行中用 class A;
在 C++ 中做了完全相同的事情。
然而,有人告诉我这是一个不好的做法,在 C 中,因为 typedef
应该创建另一个类型并且可能与之前相同的 typedef
冲突,以防多重包含。
他还告诉我,出于这些原因,在 header 守卫之外不应有任何声明。
所以,他建议我在 struct B
(和 vice-versa)的声明之前在 b.h
中放置一个 typedef struct A A;
,因为这是我需要它的地方.
我的问题是:
在这种情况下,typedef .. A;
在b.h
中丢失不是很危险吗?
更一般地说,处理这种依赖关系的最佳做法是什么?
处理这类依赖关系的最佳做法通常是避免它们。不过,这并不总是可能的。
我会这样做:
a.h
#ifndef A_H
#define A_H
#include "b.h"
// Forward decls
struct B;
typedef struct A { struct B* second_struct; } A;
#endif /* !A_H */
b.h
#ifndef B_H
#define B_H
#include "a.h"
// Forward decls
struct A;
typedef struct B { struct A* first_struct; } B;
#endif /* !B_H */
在 C 和 C++ 中均有效。
前向声明应尽可能简单,因此应避免其中的 typedef,这在本例中很简单。这仅意味着您必须在 B.
的定义中使用 struct A*
而不是 A*
关于 include 守卫之外的 typedef:这绝对不是标准做法。
#include "a.h"
确保 struct A
的前向声明存在,乍一听这听起来很诱人。问题是 struct A
可能是不完整的类型不再明显。
前向声明也是对未来的警告reader它们可能正在处理不完整的类型。
在 C 中,当我需要这个时:
文件a.h
:
#ifndef A_H
#define A_H
#include "b.h"
typedef struct A { B* second_struct; } A;
#endif /* !A_H */
文件b.h
:
#ifndef B_H
#define B_H
#include "a.h"
typedef struct B { A* first_struct; } B;
#endif /* !B_H */
我冒昧地以这种方式重新排列:
typedef struct A A;
#ifndef A_H
...
(b.h
也是如此)
我在 header 的第一行中用 class A;
在 C++ 中做了完全相同的事情。
然而,有人告诉我这是一个不好的做法,在 C 中,因为 typedef
应该创建另一个类型并且可能与之前相同的 typedef
冲突,以防多重包含。
他还告诉我,出于这些原因,在 header 守卫之外不应有任何声明。
所以,他建议我在 struct B
(和 vice-versa)的声明之前在 b.h
中放置一个 typedef struct A A;
,因为这是我需要它的地方.
我的问题是:
在这种情况下,typedef .. A;
在b.h
中丢失不是很危险吗?
更一般地说,处理这种依赖关系的最佳做法是什么?
处理这类依赖关系的最佳做法通常是避免它们。不过,这并不总是可能的。
我会这样做:
a.h
#ifndef A_H
#define A_H
#include "b.h"
// Forward decls
struct B;
typedef struct A { struct B* second_struct; } A;
#endif /* !A_H */
b.h
#ifndef B_H
#define B_H
#include "a.h"
// Forward decls
struct A;
typedef struct B { struct A* first_struct; } B;
#endif /* !B_H */
在 C 和 C++ 中均有效。
前向声明应尽可能简单,因此应避免其中的 typedef,这在本例中很简单。这仅意味着您必须在 B.
的定义中使用struct A*
而不是 A*
关于 include 守卫之外的 typedef:这绝对不是标准做法。
#include "a.h"
确保 struct A
的前向声明存在,乍一听这听起来很诱人。问题是 struct A
可能是不完整的类型不再明显。
前向声明也是对未来的警告reader它们可能正在处理不完整的类型。