0

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

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

一些可能的解决方案是:

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

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

4

4 回答 4

6

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

要完全隐藏这些函数以防止在源文件之外使用,通常需要执行以下操作之一:

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

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

在命名空间范围内声明对象时,不推荐使用 static 关键字,未命名命名空间提供了更好的选择。

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

于 2012-05-22T10:52:04.397 回答
3

如果私有函数只在单个源文件中使用,那么您不需要任何额外的头文件。只需标记函数static或使用匿名函数namespace

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

于 2012-05-22T10:54:10.143 回答
0

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

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

于 2012-05-22T11:41:59.617 回答
0

你没有提到这些“函数”是否是一个类的成员,但我会假设它们是。如果是这样,我建议您查看'pimpl idiom'。基本上,这意味着将您想要保持私有的所有或大部分内容放入一个单独的类中,然后在您的类声明中只有一个指向该类实例的指针。例如:

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

变成

class MyClassImpl;

class MyClass
{
private:
    MyClassImpl* impl_;
};

然后的想法是,您的实现类的所有声明和定义都将进入您的 .cpp 文件,该文件将其隐藏在编译单元之外的任何地方。这种方法有许多重要的优点:

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

有很多缺点:

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

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

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

namespace {

    // Your stuff goes here.

};

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

于 2012-05-22T12:15:27.823 回答