【问题标题】:difference between static functions in C++C++中静态函数的区别
【发布时间】:2013-11-18 14:20:06
【问题描述】:

任何人都可以解释类中定义的静态函数和声明的静态函数之间的区别,例如在 file.hpp 和 file.cpp 中定义(我只能在这个文件中使用这个静态函数?

【问题讨论】:

标签: c++ function static


【解决方案1】:

谁能解释类中定义的静态函数之间的区别

这意味着函数是类范围的,不需要对特定对象进行操作。换句话说,对于那个函数,没有this

和声明的静态函数,例如在 file.hpp 和 file.cpp 中定义(我只能在这个文件中使用这个静态函数?

这意味着该函数没有外部链接,这意味着其他编译单元(即目标文件)无法链接到它,因为它不在符号表中。


感谢您的回复,但您能解释一下为什么其他编译单元无法链接到它吗?

首先,一些术语。从技术上讲,编译器只是从源代码生成目标代码的部分。 链接器稍后会获取一组目标文件并“链接”它们以制作最终程序。

为了完成这项工作,编译器会生成一个“符号表”并将其与编译后的代码一起放入目标文件中。此符号表列出了文件中全局变量和函数的符号,以及代码需要链接到的外部符号才能工作。

链接器的工作是读取所有目标文件并将每个目标文件所需的符号与其他目标文件提供的符号相匹配。如果一切顺利,并且没有任何未解析的所需符号,则链接成功,您将获得您的程序。

函数或全局函数上的static 所做的只是告诉编译器不要将该符号放入目标文件的符号表中。没有其他的;该符号在同一个源文件中仍然完全可用。链接器根本看不到符号,因此无法链接任何东西。

类成员不能以这种方式“消失”,因此static 在类的上下文中具有不同的含义。 (这种关键字的循环可能是为了避免在语言中添加另一个保留字。顺便说一句,Objective-C 使用 +- 标记以不同的方式解决了同样的问题。)

(正如 Mike 在下面指出的那样,static 应用于在函数或方法中声明的变量时还有另一个含义。在这种情况下,它基本上是一个全局变量,但对函数来说是私有的。)


您能否解释一下为什么内联函数被隐式定义为静态函数?

由于内联函数不作为独立的代码段存在(而是“行内”合并到调用函数中),它们不能有符号表条目(没有可链接的内容)。

【讨论】:

  • 感谢您的回复,但您能解释一下为什么其他编译单元无法链接到它吗?每个例如某些编译单元中的函数产品某些符号,除非我们在函数名称前有静态词 - 它会改变什么吗?
【解决方案2】:

请参考这个link

函数内的静态变量在调用之间保持其值。 然而,在 C++ 中,静态也用于定义类属性(在同一类的所有对象之间共享)和方法。在 C 中没有类,所以这个特性是无关紧要的。

【讨论】:

    【解决方案3】:

    在全局范围内定义的静态函数没有区别,无论它是在头文件中还是在源文件中。除非头文件不包含在任何地方,否则其中的函数从未在任何地方真正定义过。

    那么你在谈论静态(非成员)函数时需要学习的短语是翻译单元。翻译单元是一个源文件和包含在该源文件中的所有头文件,在预处理器处理完文件之后,它是编译器的实际输入。静态函数是翻译单元的本地函数,这就是为什么在源文件或头文件中定义它没有区别。

    您还可以使用匿名命名空间来定义函数,它们将只对匿名命名空间所在的翻译单元是本地的。

    另请注意,定义为 inline 的函数也隐式定义为 static


    静态成员函数是类的一部分,可以在没有范围前缀的情况下访问静态成员变量。它们当然必须以要调用的类的范围为前缀。静态成员函数和非静态成员函数之间的区别在于静态成员函数不属于该类的任何特定实例,因此没有this 指针。如果要访问特定类的实例成员变量,则必须通过参数将实例传递给静态成员函数。

    【讨论】:

    • 感谢您的回复。我更关心的是,当我想在另一个编译单元中使用静态函数(例如,我在 file.hpp 中有声明,在 file.cpp 中有定义)时,它不起作用。当我在这个文件类中创建并将这个静态函数移到那里并在另一个编译单元中使用它时没问题,为什么?当我在类或结构中没有静态函数时,它类似于我在编译单元匿名命名空间中的情况吗?如果我在某个文件中只有静态函数,我在符号表中没有它?
    • 你能解释一下为什么内联函数被隐式定义为静态的吗?
    • −1 “还要注意,定义为内联的函数也隐式定义为静态。”不,命名空间范围内的 inline 函数默认具有外部链接。另外,第一句话对我来说没有任何意义,“在全局范围内定义的静态函数没有区别,无论它是在头文件中还是在源文件中”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-02
    • 2017-08-25
    • 2010-10-30
    • 2014-04-27
    相关资源
    最近更新 更多