C ++,私有函数真的需要在头文件中吗?

时间:2015-02-05 01:01:14

标签: c++ standards conventions

我一直认为头文件是一种“公共界面”。描述一个类,在这种情况下,最好将私有字段和函数保存在cpp文件中。

我理解私有字段需要在头文件中,以便其他类可以告诉一个类的实例将消耗多少内存,但是当我正要编写一个私有帮助函数时,我想到了这个函数,这个函数可以是静态的,在这种情况下,它不需要成为课程的一部分。完全可以,它很容易成为类定义的.cpp文件中的常规函数​​。

然后我发现 所有 私有函数可能通过接受指向类字段的指针/引用而不是期望在上课。

这将消除在头文件中声明任何私有函数的需要。

我喜欢遵循约定所以现在我想问一下,它是否被认为是C ++中的既定约定,非静态私有函数 应该 在标题中文件?静态函数或静态常量怎么样?

编辑:我将提供一些代码来解释我的目标:

.h文件:

#ifndef SOME_CLASS_H
#define SOME_CLASS_H

class SomeClass
{
private:
    int x;
public:
    void combineWithX(int y);
};

#endif

.cpp文件

#include "SomeClass.h"

void someHelper(int* x)
{
    *x = (*x) + 1;
}

void SomeClass::combineWithX(int y)
{
    someHelper(&x);
    x += y;
}

请注意,cpp文件中的someHelper(int* x)在精神中引用私有成员x,但不是直接引用,因此不需要出现在标头中。我想知道这种事情是否被认为是不好的风格'

3 个答案:

答案 0 :(得分:18)

只需要PImpl成语

  1. 如果您需要将私人会员'变量' 移出公共标题(用于维护binary compatibility新版本 - 如果您不知道什么这意味着,这可能不是一个问题)
  2. 如果该设计更容易理解
  3. 如果您只想将私有成员'功能' 移出公共标题,则使用内部类就足够了。这没有像PImpl惯用语那样的重定向惩罚。

    public .h file

    #ifndef SOME_CLASS_H
    #define SOME_CLASS_H
    
    class SomeClass
    {
    private:
        struct Private;
        int x;
    public:
        void combineWithX(int y);
    };
    
    #endif
    

    在.cpp文件中

    #include "SomeClass.h"
    
    /** Declare all private member functions of SomeClass here
        This class can access not only private members of SomeClass
        but also friends of SomeClass. */
    struct SomeClass::Private
    {
      static void someHelper(SomeClass& self)
      {
        self.x = self.x + 1;
      }
    };
    
    void SomeClass::combineWithX(int y)
    {
        Private::someHelper(*this);
        x += y;
    }
    

    SomeClass::Private可以拥有任意数量的辅助函数,可以完全访问SomeClass的所有私人/朋友,而无需在头文件中声明任何这些函数。

答案 1 :(得分:7)

我同意实现细节需要在头文件中公开是一个问题;它干扰了界面和实现的分离。

将私有帮助函数移动到.cpp文件中的自由函数(我认为这就是你所指的"静态")如果这些函数需要访问私有函数将无法工作成员变量。

您可能有兴趣查看pImpl idiom (more)

答案 2 :(得分:0)

怎么样

// MyClass.h -

MyClass {
public:
   // public stuff..

#ifdef mynamespace_myclass_p
private:
   // private stuff..
#endif // mynamespace_myclass_p

}

// MyClass.cpp - 

#define mynamespace_myclass_p
#include "MyClass.h"

// implementation code..

嗯,但是您的标头仍然到处都是私人物品。

头很疼。我可能是错的,但此刻,我感觉标头是所有C ++中痛苦/有用比率最大的东西。使用C ++进行编程时,基本上必须在至少两个地方维护所有方法签名,并且如果您不希望公共标头被私有内容弄得乱七八糟,则几乎必须拥有两个版本的标头,这意味着必须维护您的签名至少在3个地方!加上任何前锋声明都需要。严重的是,它们所带来的麻烦远远超过其价值。

我非常期待看到C ++ 20的模块系统如何发挥作用。这可能是一个巨大的福音。我们已经等待了将近5年了。