支持函数声明应该去哪里

Where should support function declarations go?

本文关键字:函数 声明 支持      更新时间:2023-10-16

>我有一个.cpp源文件,其中包含一些需要公开访问的函数和一些仅在此源文件中使用的支持函数。

我一直将所有这些函数声明放在头文件中,因为我个人发现在一个地方查看类提供的所有内容很有用。但是,我想指出这些函数是否供内部使用,类似于 private 访问修饰符,但不使用类(它们是独立的函数(。

一些可能的解决方案是:

  • 将私有声明放在源文件中。
  • 将私有声明放在单独的标头中。

这两种解决方案都将公共和私有功能拆分为单独的文件,我想避免这样做。

如果函数不打算供公众使用,则不应将 放入标头中。将它们放入使用它们的源文件中。

要完全隐藏这些功能,使其不被在源文件外部使用,通常执行以下操作之一:

  • 函数声明为 static
  • 函数被放入一个未命名的namespace中。

后者被认为是可取的。实际上,C++标准 7.3.1.1 规定:

在命名空间作用域中声明对象时,不推荐使用 static 关键字,unnamed-namespace 提供了一个更好的替代方法。

有关未命名命名空间

与静态的更多讨论,请参阅未命名/匿名命名空间与静态函数以及相应的 comp.lang.c++.moderated 线程。

如果私有函数仅在单个源文件中使用,则不需要任何额外的头文件。只需将功能标记为static或使用匿名namespace即可。

如果可以从许多源文件中使用这些函数,请在特殊namespace的单独头文件中声明它们。这是我的建议。

支持函数声明应该去哪里?

他们不必去任何地方。将它们设为静态并保存在源文件中。如果它们仅在单个源文件中使用,则无需在任何标头中提出声明。

你没有提到这些"函数"是否是类的成员,但我假设它们是。如果是这样,我建议您查看"痘痘成语"。基本上,这意味着将要保持私有的全部或大部分内容放入单独的类中,然后在类声明中仅具有指向该类实例的指针。例如:

class MyClass
{
    // ... some stuff
private:
    SecretObject obj_;
    int hiddenCall();
};

成为

class MyClassImpl;
class MyClass
{
private:
    MyClassImpl* impl_;
};

那么这个想法是,你的implemntation类的所有声明和定义都将进入你的.cpp文件,该文件对编译单元以外的任何东西都隐藏了它。这种方法具有许多重要的优点:

  • 隐藏实现,以便公开可用的标头不会泄露太多实现。
  • 可以通过删除标头中的依赖项来提高编译速度 - 如果标头包含很多,则很重要。
  • 可用于将客户端代码与不需要构建的库(如数据库 API 等("隔离"出来。

有许多缺点:

  • 如果代码隐藏在 cpp 文件中,可能会使单元测试更加棘手。就我个人而言,我发现更好的解决方案是拥有一个单独的私有头文件和实现文件,以便您可以控制代码的客户端获取的内容,但测试工具仍然可以对其进行充分测试。您可以简单地在 cpp 文件中包含 MyClassImpl 标头,但不要将其包含在 MyClass 标头中 - 这会破坏对象。
  • MyClassMyClassImpl之间的间接寻址可能令人厌烦编码/管理。

不过,一般来说,这可能是实现您想要达到的目标的最佳方式。查看Herb Sutter的文章以获得更深入的解释。

另一方面,如果您谈论的是类没有直接关系的自由函数,那么我会将它们放在 cpp 文件的未命名命名空间中。例如:

namespace {
    // Your stuff goes here.
};

同样,如果您采用这种方法,您会遇到如何访问这些函数的单元测试问题,但如果这确实是一个问题,则可以通过创建特定的命名空间、条件编译等来解决此问题。不理想,但有可能。