我对全局常量有点困惑。 我(初学者(的理解是"全局"变量是在块之外定义的,并且具有程序范围(来源:http://www.learncpp.com/cpp-tutorial/42-global-variables/(。但程序:
#include <iostream>
const double x=1.5;
int main(){
std::cout << "1) x=" << x << std::endl;
double x=2.5;
std::cout << "2) x=" << x << std::endl;
//const double x=3.5;
return 0;
}
用 g++(GCC,最新的 64 位版本(编译没有任何问题,即使使用 -Wall 也是如此。
输出:
1) x=1.5
2) x=2.5
这让我感到困惑。第一个cout评估的事实意味着main将"x"识别为"全局"变量(它没有在main的作用域中定义(。如果是这样的话,为什么它让我重新定义"x"?
然后,如果您取消注释的第三个声明,g++ 会引发重新声明错误。意思是,我的第一个声明不可能是"全局的",在我定义的意义上:S
编辑:好的,问题与全局变量无关,但范围:例如 http://pastebin.com/raw.php?i=V5xni19M 中的相同问题
#include <iostream>
const double x=1.5;
此时在代码中,全局范围内有一个名为 x
的对象,其类型为 const double
。
int main(){
std::cout << "1) x=" << x << std::endl;
在这一点上,仍然只有一个可见x
(全局的(,所以这就是x
所指的名称。
double x=2.5;
此时,在代码中,你已将一个名为 x
的对象引入main()
的范围。该作用域嵌套在全局作用域中,因此现在您有两个名为 x
的对象:
x
在类型const double
的全局范围内x
在double
类main()
范围内
本地x
隐藏了全局x
。如果要访问 main()
内部的全局x
,可以将其称为 ::x
。
std::cout << "2) x=" << x << std::endl;
double x=3.5; //uncommented
不,您正在尝试将另一个名为 x
的对象引入 main()
的范围。这是不可能的,该范围内已经有一个x
,因此它失败了。
第二个x
不是重新定义。它hiding
全球x
.这是我们需要注意的事情,尤其是在处理继承时:
struct Base
{
void AwesomeFunction() { }
};
struct Derived : public Base
{
// This definition 'hides' Base::AwesomeFunction
void AwesomeFunction() { }
};
仅允许此隐藏,因为第二个x
的范围比全局x
。您会收到第三个x
的 redfinition 错误,因为第三个和第二个x
位于同一范围"级别"。
使用 ::x 从程序中访问全局变量。现在你正在创建一个局部变量和一个全局变量。当您第一次打印x时,它找不到本地的,因此它假设您指的是全局。创建本地 x 后,它不再默认为全局。
代码中发生的情况是,如果局部变量采用相同的名称,则局部变量优先于全局变量。您可以在整个程序的任何块中使用全局变量,而局部变量将在其块(主(的末尾被处理。但是,编译器不会允许您在一个块中声明两个同名的局部变量。
允许内部作用域(如 main(中的声明在外部作用域(如文件作用域(隐藏声明。x 的第三个声明与第二个声明的范围相同,因此这是一个重新声明错误。
您不是在重新定义全局变量;而是在定义一个具有相同名称的单独局部变量。
C++允许您重用名称来声明像这样较窄范围内的其他内容;从技术上讲,内部作用域中的声明隐藏了外部作用域中的声明,因此,在声明和函数末尾之间,x
引用局部变量。您仍然可以通过使用全局变量的命名空间对其进行限定来访问全局变量:::x
。
第三个声明将尝试在同一范围内重用名称,这是不允许的。