私有静态方法是否必要?

9
在我上一个公司,The Principle Engineer 有一个规定:应将私有的静态方法作为实现文件中的函数而不是类方法实现。我不记得他是否有任何例外。在我的当前工作中,我遇到了这个规则的动机:如果问题函数的参数或返回类型是需要在头文件中包含定义文件的对象,则会导致不必要的困难。这足以让我远离使用 private static 方法,但在我放弃之前,我想知道是否有人意识到它们填补了某些特定领域的空缺,而实现文件函数无法填补。
注:下面是编辑的内容:
可以举个例子说明。假设这是声明 class Foo 的开始,该类还有其他方法将调用实现文件中的 void foo()

class Foo {
    static void foo();

所以foo只能被Foo的其他方法访问。那么为什么我不把foo定义在实现文件中,完全不在头文件中呢?


那么,如果该方法是“public”或“protected”,会有什么不同呢?你问题中引用的规则并没有解释为什么“private”会得到特殊处理。 - Christian Hackl
@Dan 我曾经考虑过这个问题,但我想不出一个能够访问 private static 方法而没有直接访问 private static 数据的情况。你有我没想到的例子吗? - Jonathan Mee
1
@ChristianHackl 我从未听说过这个。我认为只有引用和指针可以被前向声明。如果您想参与讨论,请在这里跟进:https://dev59.com/0VgQ5IYBdhLWcg3w9Ykb - Jonathan Mee
1
@user2357112:你只需要在调用站点处定义。请参见http://ideone.com/3yBY8R。 - Christian Hackl
2
@user2357112:但是在函数的声明处不需要类型定义。 - Christian Hackl
显示剩余13条评论
3个回答

12

与实现文件中的自由静态函数不同,私有静态成员函数可以在类的头文件中使用。这在您想要内联非私有成员函数并调用您的私有静态函数的情况下很重要:

class Demo {
private:
    static std::string sanitize(const std::string& name);
    std::string name;
public:
    Demo(const std::string& n) : name(sanitize(n)) {
    }
};

如果要对独立的静态函数进行相同操作,则需要在cpp文件中实现Demo的构造函数。


这是一个很棒的例子。所以也许应该将异常定义为:“当头文件中不需要该函数时”。 - Jonathan Mee
1
@JonathanMee 是的,在我使用 C++ 的日子里,我遵循了这个规则。大致意思是“除非你需要在类头文件中使用它们,否则请优先使用自由静态函数和静态变量而不是静态成员函数和静态成员变量。” - Sergey Kalinichenko
这比我的笨拙表达更好,正如在我的问题上出现的无数澄清评论所清楚证明的那样。 - Jonathan Mee
你可不可以在头文件中的类之前用前置声明声明该静态/自由函数呢?这样仍然可以内联实现构造函数。 - Daniel Stevens
虽然自由方法会添加到类外的命名空间中,但私有静态方法不会污染全局命名空间。 - Daniel Stevens

4

成员函数可以访问类中所有的私有成员。如果一个函数需要访问这些成员,它应该是一个成员函数,不论它是否是静态的。

静态函数是不针对特定对象进行操作的函数。但是它仍然可以接受对象作为参数。例如:

class A
{
    int m;

    static int process_3_objects_in_some_way(A x, A y, A z)
    {
        return x.m + y.m + z.m;
    }
}

将函数定义为static的另一个原因是参数的顺序。例如,print函数:

class A
{
    int m;

    static void print(std::ostream& stream, A x, int options)
    {
        stream << "Value is: " << (x.m * 1000000 + options);
    }
}

我猜你的第二个例子应该是 x.m 而不是 m?不过这些都是好例子。 - Jonathan Mee
只是为了保持探究,因为这些是最好的例子,我希望我的被接受的答案至少可以编译。我认为你也想让 print 返回一个 ostream&,对吧? - Jonathan Mee
当然可以!我猜这就是你没有通过编译器运行代码的结果吧...(虽然我已经将返回值完全删除了,以简化代码) - anatolyg

1

friend函数或类在另一个实现文件中实现时,是需要私有静态成员函数的另一个例子。


“friend” 不是我想要的,但我认为这是一个很好的例外。 - Jonathan Mee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接