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

C++ 支持函数声明应该去哪里?,c++,header-files,private-header,C++,Header Files,Private Header,我有一个.cpp源文件,其中包含一些需要公开访问的函数和一些仅在此源文件中使用的支持函数 我一直在将这些函数声明的全部放在头文件中,因为我个人认为在一个地方查看类提供的所有内容都很有用。但是,我想指出这些函数是否供内部使用,类似于privateaccess修饰符,但不使用类(它们是独立函数) 一些可能的解决办法是: 将私有声明放在源文件中 将私有声明放在单独的标题中 这两种解决方案都将公共和私有函数拆分为单独的文件,我希望避免使用这些文件。如果这些函数不是供公共使用的,则不应将放在标题中。将

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

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

一些可能的解决办法是:

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

这两种解决方案都将公共和私有函数拆分为单独的文件,我希望避免使用这些文件。

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

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

  • 函数声明为
    静态
  • 函数被放入一个未命名的
    命名空间
后者被认为更可取。实际上,C++标准7.3.1.1的状态是:

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


有关未命名名称空间与静态名称空间的更多讨论,请参阅和相应的。

如果专用函数仅在单个源文件中使用,则不需要任何额外的头文件。只需将函数标记为
静态
或使用匿名
命名空间

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

支持函数声明应该去哪里


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

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

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

    // Your stuff goes here.

};
变成

class MyClassImpl;

class MyClass
{
private:
    MyClassImpl* impl_;
};
这样的想法是,implementation类的所有声明和定义都将进入.cpp文件,该文件对编译单元以外的任何对象都隐藏了它。这种方法有许多重要的优点:

  • 隐藏实现,以便公共可用的头不会泄露太多的实现
  • 可以通过删除标头-v中的依赖项来提高编译速度。如果标题包含很多内容,则很重要
  • 对于将客户机代码与不需要构建的库(如数据库API等)进行“隔离”非常有用
有许多缺点:

  • 如果代码隐藏在cpp文件中,可能会使单元测试变得更加棘手。就我个人而言,我发现一个更好的解决方案是有一个单独的、私有的头文件和实现文件,这样您就可以控制代码的客户端得到什么,但测试工具仍然可以充分地测试它。您只需在cpp文件中包含
    MyClassImpl
    头文件,但不要将其包含在
    MyClass
    头文件中-这将破坏对象
  • MyClass
    MyClassImpl
    之间的间接关系对于编码/管理来说可能很烦人
一般来说,这可能是实现你想要的目标的最好方式。查看Herb Sutter的文章以获得更深入的解释

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

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

    // Your stuff goes here.

};

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

我认为问题是关于独立函数:“类似于私有访问修饰符,但不使用类”。@Daniel,我错了吗?没错,我正在使用的代码不使用类。@Daniel:我重新阅读了你的问题,以及它是关于函数(而不是方法)的事实不太清楚。也许你应该明确说明。如果静态/匿名函数没有在其他地方使用,那么将它们放在头文件中会是一种不好的做法吗?对我来说,将所有声明放在一个地方似乎是有益的。不。
#include
指令只是在文本上用包含的头文件的内容替换。因此,从头文件到它所包含的文件的所有内容都是可访问的。它们是独立的函数。这是真的。我发现将所有声明放在一个位置很方便,但我想现代IDE提供了类大纲功能,可以快速显示可用的函数。