何时应在非成员函数之前编写关键字 'static'?

When should I write the keyword 'static' before a non-member function?

本文关键字:关键字 static 成员 函数 何时应      更新时间:2023-10-16

我最近在一个函数之前看到了一些关于static关键字的SO,我想知道如何正确使用它。

1)什么时候应该在非成员函数之前写关键字static ?

2)在头文件中定义静态非成员函数是否危险?为什么(不)?


(一边提问)

3)是否有可能在头文件中以某种方式定义一个类,以便它只在您首先使用它的翻译单元中可用?

(我问这个的原因是因为我正在学习STL,它可能是我的谓词等(可能是函子)的一个很好的解决方案,因为我不喜欢在cpp文件中定义成员函数以外的函数)

(另外,我认为它在某种程度上与原始问题有关,因为根据我目前的推理,它会在函数之前做与static相同的事情)

编辑

在看到一些答案时出现的另一个问题:

4)许多人告诉我必须在头文件中声明静态函数,并在源文件中定义它。但是静态函数是翻译单元所特有的。链接器如何知道哪个翻译单元是唯一的,因为头文件不直接与源文件相关(只有当您包含它们时)?

static,我认为你正在使用它,是一种符号隐藏的手段。声明static的函数没有全局可见性(类unix的nm将显示为't'而不是't')。这些函数不能从其他翻译单元调用。

对于c++,这种意义上的static或多或少已经被匿名命名空间所取代,例如

static int x = 0;

相当
namespace {
  int x = 0;
}

请注意,每个编译单元的匿名命名空间是唯一的。

static不同的是,匿名命名空间也适用于类。你可以这样写
namespace {
 class Foo{};
}

并在其他翻译单元中为不相关的类重用该类名。我想这正是你要说的。

编译器实际上给你这样定义的每个符号一个唯一的名字(我认为它包括编译时间)。这些符号永远不会被其他翻译单元使用,也不会与其他翻译单元的符号发生冲突。

注意所有声明为inline的非成员函数在默认情况下也是static。这是static最常见的(隐式的)用法。至于第2点,在头文件中定义static而不是inline函数是一种非常极端的情况:它本身并不危险,但很少有用,可能会令人困惑。这样的函数可能会在每个翻译单元中发出,也可能不会。如果您从未在某些tu中实际调用该函数,编译器可能会生成警告。如果静态函数中有一个静态变量,那么即使在单个.h中有一个定义,每个翻译单元也会有一个单独的变量,这可能会令人困惑。只是没有很多(非内联)用例。

关于第4点,我怀疑这些人将static的静态成员函数含义与static的链接含义混淆了。这是为后者使用匿名名称空间的一个很好的理由。

关键字"static"被重载以表示几种不同的含义:

  • 它可以控制可见性(C和c++)

  • 它可以在子例程调用之间保持变量(C和c++)

    …和…

  • 它可以使方法或成员应用于整个类(而不仅仅是类实例:仅限c++)

简短的回答:最好不要使用任何语言工具,除非

a)你很确定你需要它

b)你非常确定你知道你在做什么(即你知道你为什么需要它)

在.cpp文件中声明静态变量或独立函数绝对没有错。在头文件中声明静态变量或独立函数可能是不明智的。而且,如果您确实需要类函数或类成员的"静态",那么头文件无疑是定义它的最佳位置。

这里有一个很好的链接:

http://www.cprogramming.com/tutorial/statickeyword.html

如果非成员函数只能在声明它们的代码文件中可见,则应该将其定义为静态函数。

同样的问题在cplusplus.com