在其中一个头文件中,很少有全局变量是静态的。我看到这些变量用在相关的.cc文件中。所以,看起来这没有问题。
我的问题是:
包含全局变量与静态全局变量之间的区别是什么? 我知道静态全局在其文件之外没有可见性。但是,当它作为#h的一部分出现时,不知道这是如何工作的。
我写了一个示例程序,并尝试了同样的事情。但是,当我将变量设为静态时,我会收到编译错误。当它只是全球化时,它很好。 那么,在常规的g ++构建中是否存在我缺少的东西? (请注意,最初的案例是在我们的官方代码库中,它有足够的makefile,.h文件和所有内容。)
感谢您的帮助!
这是我的示例程序:
.h文件:
#include <iostream>
typedef unsigned int uint;
static const int appk=189;
class abc1
{
public:
abc1(int x);
virtual void printVal();
};
.cc文件:
#include "abc1.h"
extern int appk;
abc1::abc1(int x)
{
}
void abc1::printVal()
{
printf("abc1 print: %d\n", appk);
}
答案 0 :(得分:4)
(1)如果将全局变量放在.h
文件中并将其包含在各种.cpp / .cc文件中,则会为每个文件定义多次。因此,您最希望得到链接器错误。
为了解决这个问题,大多数情况下您可能会使用extern
关键字:
// myfile.h
extern int i;
并在一个翻译单元中定义:
// somefile.cc
int i;
(2)如果您将static
个全局信息放入.h
文件并将其包含在内,则不会出现任何错误,因为对于每个不同的翻译单元,该static
全局变量将有一个不同的副本。
// myfile.h
static int i; // creates a unique and unrelated copy in all .cc file where included
但是,此类用法已弃用;而不是最好使用未命名的namespace
:
namespace {
int i;
}
根据您的问题,我不认为您应该为static
全局发现任何链接器错误。
答案 1 :(得分:2)
很难在没有代码的情况下告诉您的编译错误,但如果您有一个声明静态全局的标头,那么您只需在包含标题的每个翻译单元中单独创建该全局变量。
示例:
header.h:
#ifndef H_XXX
#define H_XXX
static int a;
#endif
file1.cpp:
#include "header.h"
// now have access to a variable called "a"
file2.cpp:
#include "header.h"
// now also have access to some "a"
这两个文件都可以访问名为a
的全局变量,但每个文件都有自己独立的副本,对于其翻译单元是私有的,在外面看不到。
对于一个实际示例,我认为cout
被声明为静态全局,因此使用<iostream>
的每个人都会获得自己的副本。
答案 2 :(得分:1)
static
变量具有内部链接。这意味着,如果a
中有静态变量x.h
,并且您在x.h
和m.cpp
这两个文件中包含n.pp
,那么这两个文件中的每一个都是文件获取自己的a
副本,这意味着如果您在m.cpp
中更改其值,则n.cpp
将不会看到该更改,因为每个翻译中存在两个具有相同名称的变量单位(.cpp)。而且他们彼此独立。
但如果a
不是静态的,那么在多个文件中包含x.h
,就会出现多重定义错误,因为x.h
的每个包含都会尝试定义{{ 1}},但因为a
不是静态的;它现在有外部链接,这意味着如果它在a
中定义,那么在m.cpp
中包含x.h
时会出错(反之亦然)。在这种情况下,您需要将n.cpp
写为:
x.h
然后在//x.h
extern int a;
或a
的{{1}}文件中定义.cpp
,但不能同时在两者中定义m.cpp
。说出n.cpp
。
m.cpp
你已经完成了。现在,您可以根据需要在//m.cpp
#include "x.h"
int a =10;
个文件中包含x.h
,并可以访问.cpp
,修改其值,随心所欲。现在,所有a
个文件都会看到对它的任何更改。