我一直认为头文件是一种“公共界面”。描述一个类,在这种情况下,最好将私有字段和函数保存在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,但不是直接引用,因此不需要出现在标头中。我想知道这种事情是否被认为是不好的风格'
答案 0 :(得分:18)
只需要PImpl成语
如果您只想将私有成员'功能' 移出公共标题,则使用内部类就足够了。这没有像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年了。