显式直接#include 与非契约传递#include

2024-06-18

假设我们有这个头文件:

我的类.hpp

#pragma once
#include <vector>

class MyClass
{
public:
    MyClass(double);

    /* ... */

private:
    std::vector<double> internal_values;
};

现在,每当我们使用#include "MyClass.hpp"在其他一些 hpp 或 cpp 文件中,我们实际上也#include <vector>,尽管事实上我们不需要它。我之所以说不需要是因为std::vector仅在内部使用MyClass,但这根本不是必需的与这个班级实际互动.

结果,我可以写

版本 1:SomeOtherHeader.hpp

#pragma once
#include "MyClass.hpp"

void func(const MyClass&, const std::vector<double>&);

而我可能should write

版本 2:SomeOtherHeader.hpp

#pragma once
#include "MyClass.hpp"
#include <vector>

void func(const MyClass&, const std::vector<double>&);

防止对内部运作的依赖MyClass。或者我应该?

我显然意识到MyClass needs <vector>上班。所以这可能更像是一个哲学问题。但是,能够决定导入时公开哪些标头(即限制加载到命名空间中的内容)不是很好吗?这样每个标头都需要#include what it需要,而不是通过隐含地包含一些东西来逃脱another链下需要标头吗?

也许人们还可以了解即将推出的 C++20 模块,我相信这些模块可以解决这个问题的某些方面。


以防止对 MyClass 内部工作的依赖。或者我应该?

是的,您应该并且几乎出于这个原因。除非你想指定 MyClass.hpp 保证包含<vector>,你不能依赖其中之一,也不能依赖另一个。并且没有充分的理由被迫提供这样的保证。如果没有这样的保证,那么您依赖于 MyClass.hpp 的实现细节,该实现细节将来可能会发生变化,这将破坏您的代码。

我显然意识到 MyClass 需要向量才能工作。

可以?例如不能使用boost::container::small_vector反而?

在此示例中,MyClass 需要 std::vector

但MyClass未来的需求又如何呢?课程不断发展,今天的班级所需的内容并不总是与明天的班级所需的内容相同。

但是,能够决定导入时暴露哪些标头不是很好吗?

阻止传递包含是不可能的。

C++20 中引入的模块是可以用来代替 pp-inclusion 的功能,旨在帮助解决此问题。

现在,您可以通过使用 PIMPL 模式(“指向实现的指针”)来避免包含任何实现细节依赖项。但 PIMPL 引入了一个间接层,更重要的是,需要动态分配,这会影响性能。根据具体情况,这些影响可能可以忽略不计,也可能很重要。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

显式直接#include 与非契约传递#include 的相关文章

随机推荐