将静态变量从CPP文件访问到其他头文件

Zac*_*Lee 0 c++ static-linking

我正在尝试从CPP文件访问其他头文件中的静态变量。

“ Boo.hpp”

#ifndef Boo_hpp
#define Boo_hpp

static int num;

class Boo
{
public:
    Boo()
    {
        num = 35;
    }
};

#endif /* Boo_hpp */
Run Code Online (Sandbox Code Playgroud)

“ Foo.hpp”

#ifndef Foo_hpp
#define Foo_hpp

class Foo
{
public:
    Foo();
};

#endif /* Foo_hpp */
Run Code Online (Sandbox Code Playgroud)

“ Foo.cpp”

#include "Foo.hpp"
#include "Boo.hpp"
#include <iostream>

Foo::Foo()
{
    std::cout << "Num : " << num << '\n';
}
Run Code Online (Sandbox Code Playgroud)

“ main.cpp”

#include <iostream>
#include "Foo.hpp"
#include "Boo.hpp"

int main()
{
    Boo boo;
    Foo foo;
}
Run Code Online (Sandbox Code Playgroud)

我得到的结果:

Num : 0
Program ended with exit code: 0
Run Code Online (Sandbox Code Playgroud)

我期望的结果:

Num : 35
Program ended with exit code: 0
Run Code Online (Sandbox Code Playgroud)

如果将类Foo的构造函数实现从Foo.cpp移到Foo.hpp,我的代码将按预期工作。

不过,我想能够访问num从Foo.cpp。

我应该如何修正我的代码?

Som*_*ude 5

所有包含 的翻译单元Boo.hpp都有自己的num变量定义。没有其他 TU(翻译单元)将具有相同的num变量。

这就是static 链接存储修饰符的意思(对于非局部、非成员变量)。


hyd*_*yde 5

您需要了解两件事,以了解此处发生的情况。

  1. 在C ++中,头文件只是直接或间接“复制粘贴”到每个包含它们的.cpp文件的文本。由此产生的预先编写的源代码是“编译单元”,因此您基本上可以将一个.cpp文件视为一个编译单元。

  2. static全局变量(不要与类的静态成员变量,AKA类变量(与非静态全局变量基本相同...)混淆)在定义它们的编译单元内部可见。两个编译单元,它们是完全独立的变量,并且不会相互干扰(它们的名称在编译单元外部也不可见)。因此,除非您知道确实要在多个.cpp文件中单独存储变量副本(非常罕见),否则不应该将静态全局变量放在.h文件中(extern通常,在.cpp文件中定义的全局变量声明是想要在.h文件中)。

现在,当您将这两件事结合在一起时,您将意识到.h文件中定义的静态变量与.cpp文件中定义的静态变量没有什么不同。如果.h文件包含在多个.cpp文件中,则将获得该变量的多个副本,并且使用哪个变量取决于它是哪个.cpp文件(直接或通过包含)。

您有两个.cpp文件,这两个文件都在此处定义了相同的静态变量,因此它们具有两个副本,并且在这些文件中编译的代码将使用不同的变量。


现在这里有个额外的怪癖。如果您定义一个成员函数,包括构造函数,则是内联的(在类内部定义时隐式发生,如果在.h文件中定义它,但在类外部则必须使用inline关键字),则每个.cpp文件都会得到一个该功能的不同副本。现在,作为程序员,您保证它们将是相同的,这就是什么inline意思(与内联优化几乎没有关系)。如果您具有同一构造函数的多个副本(在.h文件中定义),并且它们实际上访问了不同的静态变量,则它们是不相同的,您将无法兑现承诺。不要那样做!