在 Header 中定义的全局变量。其他函数调用可以看到其变化

Global variables defined in Header. Other function call can see its changes

提问人:pvasbob 提问时间:9/20/2023 最后编辑:pvasbob 更新时间:9/21/2023 访问量:47

问:

我有一个 .h 文件和两个 .cpp 文件:

global_var.h fun.cpp main.cpp

详情如下:

global_var.h:

    extern int a;
    void fun();

趣味.cpp

    #include <iostream>
    #include "global_var.h"
    
    
    void fun()
    {
            int a = 10;
            std::cout << "Print out in  fun() " <<  a << std::endl;
    }
    

main.cpp

    #include <iostream>
    #include "global_var.h"
    
    int main()
    {
            int a;
            fun();
            std::cout << "Print out in main: " <<  a << std::endl;
    
            return 0;
    }
    

还有一个 makefile:

    ALL = main.o fun.o
    Target = main
    CC = g++
    
    $(Target): $(ALL)
            $(CC)  -o $(Target) $(ALL)
            
    
   
    clean:
            rm *.o
    

代码的输出是:

    Print out in  fun() 10
    Print out in main: 0

在 main 函数中,对 fun() 的调用将 a 修改为 10,然后在 main 中再次打印出 a。我认为fun()的变化也可以在main中看到,所以我期望的输出是:

    Print out in  fun() 10
    Print out in main: 10

知道如何实现这一目标吗?

我的最终目标是拥有如下结构:

global_var.h
// 定义(或声明。如果我使用了错误的术语,请纠正我)所有变量都共享给下面定义的所有函数。

func1.h func1.cpp /
/ 包含global_var.h,定义func1,可以在global_var.h中使用或修改变量

func2.h func2.cpp /
/ 包含global_var.h,定义 func2 可以使用或修改 global_var.h 中的变量

.......

main.cpp
//包含上面的所有 .h 文件。这里的函数调用可以看到其他函数调用引入的变量的修改。

谢谢!

C++ 变量 全局 共享

评论

0赞 Scott Hunter 9/20/2023
请用您要询问的语言标记此问题。
3赞 pptaszni 9/20/2023
int a = 10;函数内部隐藏全局变量。你是说吗?无论如何,你的设计看起来是个坏主意。a = 10;
1赞 Yunnosch 9/20/2023
你说你在标题中定义了一个全局变量(你不应该......),但我只看到它在那里声明(好)。你在哪里定义全局?也许你需要提供一个最小的可重现的例子来证明这一点。a
0赞 pvasbob 9/20/2023
@pptaszni我试着去掉“int”。然后,编译者抱怨为“未定义的引用 a 到'a'。顺便问一下,您能解释一下实现这一目标的良好设计吗?谢谢!
0赞 Pepijn Kramer 9/20/2023
为什么你认为全局变量是个好主意?现在可能看起来很方便,但以后可能会很痛苦。了解全局变量的优缺点。TLDR 有缺点。

答:

3赞 Caleth 9/20/2023 #1

您尚未定义全局变量。您已经声明了一个变量,然后在两个不同的地方定义了具有相同名称的局部变量。注意,您的程序具有未定义的行为,因为您使用了 的值 而没有初始化它。maina

你是故意这样做的吗?

趣味.cpp

#include <iostream>
#include "global_var.h"

int a; // definition at namespace scope.

void fun()
{
        a = 10; // assignment, not definition with initialiser
        std::cout << "Print out in  fun() " <<  a << std::endl;
}

main.cpp

#include <iostream>
#include "global_var.h"

int main()
{
        // a is declared in the header, don't declare it again
        fun();
        std::cout << "Print out in main: " <<  a << std::endl;

        return 0;
}

但是,我对全局可变状态的建议是:不要。随着程序规模的增大,你会发现越来越难推理任何单个部分的作用,因为你无法跟踪它读取和写入的状态。

评论

0赞 pvasbob 9/21/2023
谢谢!成功了。如果我必须有其他函数共享的变量,我该怎么做?
0赞 heap underrun 9/21/2023
@pvasbob 然后定义一个 .然后,共享变量需要成为 () 成员变量,而函数(使用这些成员变量)将成为成员函数。classprivate
0赞 Caleth 9/21/2023
@pvasbob将引用作为参数传递给函数。
0赞 Peter 9/21/2023 #2

你的标题确实如此

 extern int a;

不是(与您的描述相反)的定义。它是 的声明。尽管所有变量定义都是(类型)声明,但并非所有变量声明都是定义。aa

您的任何源文件中都没有对此进行定义。a

相比之下,两者都定义了一个变量,该变量是各自功能块的局部变量,名为 。所以 in 与 in 不同。此外,这两个 s 都与标头中声明的 s 不同。有些人会说函数中的 s 隐藏了标头中声明的 s(这意味着,在这两个函数中,每个函数中定义之后的用法指的是本地的,而不是标头中声明的那个)。main()fun()aamain()afun()aaaaaa

程序从不使用标头中声明的变量。因此,您的程序可以成功构建(尽管声明了标头中的变量,但它未在任何地方使用,因此不需要定义)。a

如果我们要更改您的一个(且只有一个)源文件以添加另一个函数

void fun2()
{
        a = 10;
        std::cout << "Print out in  fun2() " <<  a << std::endl;
}

这与你的工作方式不同,因为前面的内容已被删除。这是一个很小的变化(大约三个删除的字符),但效果是显着的;fun2()fun()inta = 10

  • in 的用法为 DOES 为标头中声明的变量赋值。afun2()a
  • 由于使用了标头中声明的变量,因此必须对其进行定义。
  • 如果没有定义,那么在大多数工具链中,您的程序将编译(在将 .cpp 文件转换为对象的意义上),但不会链接(即不会从目标文件生成可执行文件,如果没有可执行文件,您的程序就无法运行)。

如果你想被调用,那么你可以在某处添加它的调用(例如,如果你在上面的 main.cpp 中定义,请从 调用它)。fun2()fun2()main()main()

为了使我们修改后的程序成功构建,我们现在需要定义那个讨厌的.这必须在一个(并且只有一个)源文件中完成,在 ing 标头之后(以及任何函数之外),像这样的一行a#include

  int a;     // alternatively   int a = 42; to initialise to non-zero

请注意,如果将其添加到多个源文件中,则会破坏单一定义规则(实际上,这通常意味着由于多次定义符号,程序将不会链接)。

但是,除非您进行适当的修改,否则它们都不会引用标头中声明的内容。fun()main()a