我的类定义分布在标题和源文件中:
// T.hpp
class T {
public:
void foo();
};
// T.cpp
void T::foo() {
}
如果T::foo
需要使用一些需要只显示 T
的辅助函数,那么以下哪种解决方案最好?
// T.hpp
class T {
public:
void foo();
private:
void helper();
};
// T.cpp
void T::foo() {
helper();
}
void T::helper() {
}
// T.hpp
class T {
public:
void foo();
};
// T.cpp
namespace {
void helper() {}
}
void T::foo() {
helper();
}
除了前者之外,我会在头文件中找到更多函数吗?
答案 0 :(得分:8)
首选免费的非朋友函数而不是成员函数,因为它们对类成员的访问权限少于成员函数,因此很少有机会引入错误。
如果函数完全在接口范围之外,那么也将它放在实现文件中的未命名命名空间中。这将进一步减少错误的可能性,因为其他翻译单元将无法调用该函数。
在未命名的命名空间中与非朋友一起获得的另一个好处是,您更改标题的可能性较小(因为那里的实体少了一个)。由于编译时依赖性,更改头文件通常会大大减慢构建时间。私有与否,你可能会有很多翻译单元,这取决于标题中所有内容的编译。
答案 1 :(得分:5)
需要访问私有成员的自由函数无论如何都需要在标题中使用友元声明,因此它们可能并不比私有成员函数更好。
不需要私有访问的函数应该是自由函数,无论它们是否在标题中声明。
因此,如果他们需要访问私人会员,那么让他们成为会员。否则让它们成为自由函数。
Scott Meyers有这个算法用于判断与C类相关的函数f是否应该是成员,朋友非成员或非成员非朋友:
if (f needs to be virtual) make f a member function of C; else if (f is operator>> or operator<<) { make f a non-member function; if (f needs access to non-public members of C) make f a friend of C; } else if (f needs type conversions on its left-most argument) { make f a non-member function; if (f needs access to non-public members of C) make f a friend of C; } else if (f can be implemented via C's public interface) make f a non-member function; else make f a member function of C;
答案 2 :(得分:1)
据我所知,你已经得到了它。除了你的头文件将不必要地增长之外没有区别。不过,您可能还会在类的API中泄漏一些实现细节。
答案 3 :(得分:1)
是的,存在差异
如果函数不是类的一部分,那么如果它们不依赖于这个特定的类会更好:
您可能希望在另一个类中使用它们,在这种情况下,将它们移动到某个共享位置并在两个类中使用都非常容易
如果函数(可以是一个自由函数)将第三方类作为参数并且如果使其成为成员函数,则必须包含另一个.h文件(具有此类定义)或声明你的.h文件中的这个类。这意味着更多的耦合,这是不好的:)
所以我更愿意将它们写成免费的(如果它们不是(并且可能不会)在其他类中使用,可能在未命名的命名空间中的.cpp文件中)