如何使用命名空间中的变量

How to work with variable in namespace

本文关键字:变量 命名空间 何使用      更新时间:2023-10-16

我想我对命名空间和/或静态变量有一个根本的误解。但是我已经尝试过这个测试代码(手动输入,请原谅错别字(

测试.h:

namespace test{
   static int testNum=5;
   void setNum(int value);
}

主.cpp:

#include <test.h>
int test::setNum(int value){
   testNum=value;
}
int main(){
    test::setNum(9);
    cout<<test::testNum;
}

当我运行它时,我得到的值是 5,而不是我预期的 9。 看起来好像我有两个 testNum 变量的实例,但这似乎与静态应该做的事情完全相反。 我猜我犯了一个错误,假设这些功能以某种方式与他们的 java 等同符相同......

我还收到一个错误,指出如果我从 testNum 声明中删除静态,则 testNum 被声明为多次时间,有人可以解释为什么会这样吗?

谢谢

首先

,您的误解与命名空间无关,仅与static有关。对于这个答案的其余部分,我将简单地提到testNum因为它在命名空间中的事实无关紧要。

我还假设您有另一个文件,可能称为 test.cpp ,其中还包括test.h并定义了setNum函数。

当命名空间范围内的变量或函数(即不是类成员或函数的本地(被声明static时,这意味着实体的名称是该文件的内部名称。正式地,它具有"内部链接",这意味着它不能通过名称引用或从其他文件链接到(可以通过指针间接引用它,也可以通过将其作为参数传递给另一个函数来间接引用。这意味着如果多个文件定义了static int testNum那么每个文件都有自己的内部变量,该名称,不同于每个其他文件中的testNum(实际上一个文件可能有static int testnum,另一个文件可能有static double testnum和另一个static char* testNum,它们都是不同的,并且是每个文件的内部。 如果您在标头中放置这样的定义,则包含标头的每个文件都有自己的testNum

因此,在标头中对变量进行static后,您可以在包含 test.h 的每个文件中都有一个名为 testNum 的不同变量。这意味着,如果您在一个文件中设置testNum并在另一个文件中调用一个函数,该函数使用testNum它引用了不同的变量,该变量恰好具有相同的名称。

因此,在标头中声明非常量static变量几乎总是错误的。

如果没有static,您将在每个包含 test.h 的文件中定义 testNum 变量,这是不允许的:每个实体必须定义一次,并且只能在程序中定义一次。解决这个问题的方法是在标头中声明变量,但不定义它,您可以通过告诉编译器变量extern来实现:

extern int testNum;  // N.B. no "= 1" here

这告诉编译器有一个带有"外部链接"的变量称为testNum,所以当代码引用testNum时,它总是意味着相同的变量(而不是每个文件中具有不同实体的内部 linakge 名称(。 声明extern变量后,您有责任确保程序中某处只提供了一个定义,因此在一个文件中(即不在包含在多个文件中的标头中(中定义它:

int testNum = 1;
命名空间

范围内的static用词不当,不应使用。 它简单地表示声明为 static 的实体具有内部名称绑定;换句话说,其他翻译单元中的相同名称将引用到不同的实体,在变量定义的情况下,每次翻译中都会有一个单独的变量实例单位。 它对寿命没有影响。 (声明的所有变量或在命名空间范围内定义具有静态生存期。

命名空间范围内的static也已弃用。 不要使用它。

关于在标头中声明变量:在前面加上前缀 extern,而不是static。 如果变量声明为 extern ,并且没有初始化,声明不是定义。 之当然,在这种情况下,您必须在某处提供定义(在单个源文件(。 大致如下:

extern int testNum = 5;
int testNum = 5;
int testNum;          //  implicitly initialized with 0.

编辑:

稍微澄清一下:这里存在一些混淆,介于终身和名称绑定:

  • 对象具有生存期(自动、静态或动态,或临时或异常(,并且
  • 名称
  • 绑定到实体;如果名称声明为变量,则实体是对象。

不要将关键字 static 与静态生存期混淆。 (函数可以static,但函数在C++中没有定义的生存期;他们是就在那里。

关于这些的规则不是很正统。 基本上,随着关于终身:

  • 在命名空间范围内声明的所有变量都具有静态生存期,始终,
  • 在局部范围内声明的变量具有自动生存期,除非它们被声明为 static ,并且
  • 在类范围内声明的变量具有包含它们的类对象的生存期,除非它们被声明为 static 。关于一生。

具有静态生存期的对象在main之前某个时间出现,并且一直活到你从main回来。

关于名称绑定:

  • 在命名空间范围内声明的变量具有外部名称绑定,除非它们被声明为static,在这种情况下,它们具有内部名称绑定(但不推荐使用 static(,或者如果它们是 const,并且未声明为extern
  • 在类作用域声明的变量具有外部名称绑定,即使它们被声明为 static ,并且
  • 在块范围内声明的变量没有绑定。

最后,还有一个问题,即声明是否是一个定义。或不。 如果是定义,则分配内存,对象为(或可能(初始化。 如果它不是一个定义,它只是告诉编译器,该实体在其他地方有定义(对象(在声明中声明。 通常,变量声明是一个定义,除非它被声明extern并且确实没有初始值设定项。

你可能想确保你的代码确实有问题,然后再发布它,询问它出了什么问题;)

我复制/粘贴并修复了您的拼写错误,并手动执行了包含:

#include <iostream>
using namespace std;
namespace test{
   static int testNum=5;
   void setNum(int value);
}
void test::setNum(int value){
   testNum=value;
}
int main(){
    test::setNum(9);
    cout<<test::testNum;
}

结果:

$ ./a.out 
9

你没有说的是你的程序中还有什么。如果你不仅仅是main.cpp,并且包含你的test.h,那么每个.cpp文件都有自己的testNum副本。如果您希望他们共享,那么除了一个之外,您需要将其标记为extern