如何解决库间包含依赖关系?

How do I resolve inter-library include dependencies?

我编写了一个 C++ 库(我们称之为 PhysicsLib),它使用 Bullet 库进行一些物理计算。我创建了一个 class PhysicsClass,它在自己的头文件 PhysicsClass.h 中包含了 Bullet 的两个头文件,以便访问一些 Bullet classes.

当使用这个 PhysicsLib 库时,必须包含使用的 classes——一如既往——但是当使用 PhysicsClass 时这会导致问题。当我创建应用程序 PhysicsApplication 并包含 PhysicsClass.h 时,编译器会注意到此头文件又依赖于 Bullet 中的头文件。现在,当我要编译我的应用程序 PhysicsApplication 时,我不仅要指定 PhysicsLib 的包含目录,还要指定 Bullet 的包含目录。

有哪些解决方案? 我是否只转发声明 PhysicsClass 使用的 Bullet 中的每个 class? 我从来不需要转发声明来自第三方库的 classes ,这让我质疑我的图书馆 PhysicsLib 的设计。

您基本上有两个选择:要么让 Bullet 成为您图书馆 界面的一部分, 要么将其使用限制在您图书馆的 实现中。

界面

第一个就是您现在正在做的事情:在您的库的界面部分使用 Bullet 类型、函数等,因此“承认”为了针对您的库、客户端进行开发代码也必须设置 Bullet 才能在开发中使用。

您应该在您的文档中预先说明这一点,并且根据您为客户提供的构建机制,让 Bullet 的设置尽可能成为他们的一部分。例如:如果您正在使用 CMake 并为您的库发送包配置文件,则该包配置文件应该找到 Bullet 并在您的库的接口属性中进行设置,否则无法找到 Bullet 的错误。

如果您的库有安装程序(或 installer-like 之类的东西),您可以考虑提供一个仅包含您的库的版本,另一个也包含 Bullet 的版本。

实施

另一种选择是将您对 Bullet 的使用仅限于实现。这实际上意味着“隐藏”您正在使用 Bullet 的事实。您的库的接口 header(= header 用于客户端消费)可能引用 Bullet 中的任何内容。使用 Pimpl 和类似的习语来保持 Bullet implementation-only。如有必要,将 Bullet 类型包装在您自己的不透明包装器中,以便 Bullet 后端仅保留在您的库的实现中。