如何使用命名空间中的变量
How to work with variable in namespace
我想我对命名空间和/或静态变量有一个根本的误解。但是我已经尝试过这个测试代码(手动输入,请原谅错别字(
测试.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
。
- 在命名空间 c++ 中正确声明 extern 变量
- 在命名空间中声明变量,在 main 中定义它,使其对所有其他文件可见
- 在命名空间中定义变量
- 初始化命名空间中的变量是否类似于将它们初始化为类成员?
- 如何访问嵌套在命名命名空间中的未命名命名空间变量?
- 命名空间内C++变量声明
- C++从 std::async 函数读取命名空间中的全局变量标志
- 在命名空间中声明变量
- 如何在命名空间中初始化外部变量
- 无法在命名空间范围内分配变量
- 在命名空间中定义变量,但在测试中获取空值
- 在Visual Studio中生成的匿名命名空间变量的损坏名称的数字部分是什么意思
- C++:.cpp中"Redeclare"外部命名空间变量
- 为什么主可执行文件和 dlopen 加载的共享库共享命名空间静态变量的一个副本?
- 在同一命名空间中声明变量和函数是否出错?[C++]
- 作用域中定义的变量与注入该作用域的命名空间变量
- 为什么我不能在标头中只定义一个非常量 gloabal 变量?如果我使用命名空间,为什么我必须声明它"extern"?
- 获取封装在命名空间中的静态变量地址
- 命名空间中的全局变量会导致"undefined reference to"
- 使用命名空间的全局变量