我可以包含全局静态成员吗​​?

时间:2011-08-14 17:21:00

标签: c++ static include global

在其中一个头文件中,很少有全局变量是静态的。我看到这些变量用在相关的.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);
}

3 个答案:

答案 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.hm.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个文件都会看到对它的任何更改。