【问题标题】:What is the reason and the meaning to use static non-member functions in C++?C++中使用静态非成员函数的原因和意义是什么?
【发布时间】:2021-10-08 04:33:36
【问题描述】:

想知道在C++中使用静态非成员函数是什么意思

还有为什么要使用那些而不是非静态的。

作为参考,我正在阅读 this questionthis question in other site 并在其中说

表示你不能从另一个cpp文件调用它

在我的情况下,我有一个 .h 文件和一个“主”cpp 文件。 我已经在 h 文件中实现了一个函数作为静态和非静态非成员函数,我可以从 cpp 文件中调用它,结果没有变化

所以我想知道为什么以及静态的区别或效果是什么

注意:请注意,这个问题涉及静态:

  • C
  • 成员函数
  • 变量

【问题讨论】:

  • 使用static时可以有相同的符号名称。 IE。 main.cpp 中的Foo 与 bar.cpp 中的Foo 完全无关。没有违反单一定义规则。

标签: c++


【解决方案1】:

链接整个程序和从多个地方调用函数时会看到差异。

如果foo.cppbar.cpp 包括implementation.h,对于static int baz() { return 0; },方法baz 将独立存在于foo.cppbar.cpp 的编译单元中。

当方法是非静态(非内联)时,方法baz 被所有知道原型的编译单元认为是可链接的。在这种情况下编译gcc foo.cpp bar.cpp 将导致baz 的多个引用的链接错误。

【讨论】:

  • 如果方法是非静态的但内联的会发生同样的事情吗?
  • 非静态内联函数不会导致链接错误,因为它也不会产生可链接项。
【解决方案2】:

在大多数 C++ 实现中,每个.cpp 文件都被编译成对应的.o 文件。 .o 文件包含.cpp 文件功能的目标代码 - 即 CPU 需要执行的机器代码指令才能执行这些功能。

对于非静态函数,.o 文件还包含链接器可读的元数据;即.o 文件中存在的(损坏的)函数名称列表,这些函数位于文件中,等等。在链接时,链接器将使用此元数据来解析对这些函数的调用从其他 .cpp 文件中。

对于静态函数,OTOH,.o 文件确实包含任何元数据;就链接器而言,静态函数不存在。静态函数实际上是“秘密”的,仅适用于同一 .cpp 文件中的其他代码(它不依赖于链接器来访问静态函数,因为它被编译为同一编译单元的一部分,并且因此可以直接引用它们)

在您的情况下,您在 .h 文件中实现了静态函数,这意味着该函数的单独副本包含在每个使用该函数的 .cpp 文件的 .o 文件中,这就是为什么它仍然对您“有效”。

人们经常使用static 作为一种私有命名空间标记,以保证不会从它们出现的.cpp 文件之外调用函数。在C++ 中,可以使用匿名命名空间来实现类似的结果。

【讨论】:

    【解决方案3】:

    正如其他人解释的那样,在 C++ 中,如果您的代码由多个文件组成,那么所有全局函数和变量默认都具有 external linking。例如,在文件A.cpp 中定义的函数可以通过编译器自动链接在文件B.cpp 中调用。请记住,您必须分别编译这两个文件,稍后您将告诉编译器链接这些对象.o 文件。编译器会将所有内容拼接在一起。正如我在下面的Makefile 中所做的那样。

    但是,如果您想禁用external linking,您将创建您的函数static,所以现在您的函数或变量仅可用于声明它的文件。这称为internal linking

    内部链接用于你必须有全局变量,但你不希望你的全局变量在这个文件之外被访问,而其他一些文件意外地修改它。

    为了更好地理解这个工作是如何使用这段代码的:

    first.cpp

    #include <iostream>
    /*static*/ void hello(){ //static will not let this code compile
        std::cout << "Hello I am external linking" << std::endl;
    }
    

    ma​​in.cpp

    void hello();
    int main(){
        hello();
    }
    

    生成文件

    program: first.o main.o
        g++ main.o first.o -o test
    
    main.o: main.cpp
        g++ -g -c main.cpp -o main.o
    
    
    first.o: first.cpp
        g++ -g -c first.cpp -o first.o
    

    这可以按您的预期工作。但是如果你把static放在first.cpphello()的开头,这将变成内部链接,所以你会得到编译器的链接错误。

    【讨论】:

      猜你喜欢
      • 2012-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-27
      • 1970-01-01
      相关资源
      最近更新 更多