c++ - 如何避免仅标头库中的循环依赖?
问题描述
我正在开发一个 C++ 标头库。
有几个部分的代码遵循这种模式:
持有人.h
#pragma once
#include "sub.h"
struct Holder
{
void f();
Sub s;
};
子.h
#pragma once
struct Holder;
struct Sub
{
void g(Holder& h);
};
#include "sub.ipp"
子.ipp
#include "holder.h"
inline void Sub::g(Holder& h)
{
h.f();
}
sub.h使用前向声明避免了对Holder的循环依赖。但是,在holder.h中,由于Holder类包含一个Sub成员,它需要在sub.h中查看Sub的完整声明。但是sub.h 引入了sub.ipp中的实现,它还不能被实例化,因为它需要Holder的定义并且我们已经在holder.h 中,所以我们不能再次包含它。
当我使用这些头文件中的任何一个时,我只想包含正确的.h文件,而不必担心在陌生的地方手动包含正确的.ipp文件。
对此的标准解决方案是什么?
解决方案
struct Sub { void g(Holder& h); }; void Sub::g(Holder& h) { h.f(); }
非内联函数在只有标头的库中不能很好地工作,因为标头通常包含在多个翻译单元中。您应该改用内联函数。
如何避免仅标头库中的循环依赖?
您必须将函数的定义与类的定义分开。我的意思是,它们已经在单独的文件中,但是定义类的标头不能包含函数定义。这允许打破依赖循环。
这可能是个人喜好问题,但我也不喜欢不能独立工作的“ipp”标头。
例子:
细节/holder_class_only.h
#pragma once
#include "detail/sub_class_only.h"
struct Holder
{
inline void f(); // note inline
Sub s;
};
详细信息/sub_class_only.h
#pragma once
struct Holder;
struct Sub
{
inline void g(Holder& h); // note inline
};
细节/holder_functions.h
#pragma once
#include "detail/holder_class_only.h"
void Holder::f()
{
}
#include "detail/sub_functions.h"
细节/sub_functions.h
#pragma once
#include "detail/sub_class_only.h"
#include "holder.h"
void Sub::g(Holder& h)
{
h.f();
}
子.h
#pragma once
#include "detail/sub_class_only.h"
#include "detail/sub_functions.h"
持有人.h
#pragma once
#include "detail/holder_class_only.h"
#include "detail/holder_functions.h"
注意:未经测试,可能包含错误。
推荐阅读
- typescript - 对象数组特定值的类型定义
- javascript - 可以将缩小文件导入nodejs项目吗?你如何在许多其他 npm 项目中导入外部本地模块?
- c# - 宇宙数据库。如何从 Upsert 操作中检索 _ts 属性
- rust - 在 Rust 中第 n 次出现字符时拆分字符串
- yaml - 如何通过 bash 命令将 txt 文件转换为 yml 文件?
- linux - 我无法使用 curl 运行 pastebin 脚本
- javascript - Angular:关于 Websocket 重新连接的问题
- python - 将变量设置为对象时,将其设置为内部的所有嵌套对象
- mysql - sqlalchemy 在检查并纠正 SQL 时不支持的格式字符
- angular - PrimeNg 组织结构图以编程方式刷新