范围解析运算符::
可用于访问由局部声明隐藏的全局变量。对于在封闭范围内声明但不在全局范围内声明的变量,您如何实现相同的目的?
int main() {
int i = 10;
if (1) {
int i = 5;
std::cout << "Local i: " << i << std::endl;
std::cout << "Main's i: " << ?? << std::endl; //How to access main's i?
}
return 0;
}
我知道这是不好的做法。但是我只是想知道这是否可行。我认为不是。
解释为什么不可能或为什么有用的解释。
答案 0 :(得分:5)
很遗憾,这是不可能的。诸如GCC的-Wshadow
之类的编译器警告选项可以帮助避免这种情况:
-影子
当局部变量或类型声明遮盖另一个变量,参数,类型,类成员(在C ++中)或实例时发出警告 变量(在Objective-C中)或内置函数被遮盖时。 请注意,在C ++中,如果局部变量遮盖了 显式的typedef,但如果它遮盖了struct / class / enum,则不是。如同 -Wshadow = global。
例如,在your example中,您会收到类似以下的警告:
:在函数'
int main()
'中::7:9:错误:声明'
i
'遮盖了以前的本地 [-Werror = shadow]7 | int i = 5; |
正如@L. F.在下面的评论中指出的那样,您可以使用引用来访问其他i
:
#include <iostream>
int main() {
int i = 10;
if (1) {
int& nonlocal_i = i; // just before shadowing
int i = 5;
std::cout << "Local i: " << i << std::endl;
std::cout << "Main's i: " << nonlocal_i << std::endl;
}
return 0;
}
但是-Wshadow
仍然会抱怨,如果要加倍努力寻找替代名称,则可以仅以不同的方式命名本地i
。
注意:
正如user4581301在评论中指出的那样,像int& i = i;
这样的代码在内部作用域中并没有达到您的期望:
#include <iostream>
int main()
{
int i = 4;
{
int& i = i;
std::cout << i;
}
}
它将尝试使用变量i
对其进行初始化。在Microsoft的编译器中,您会看到类似以下的编译错误:
错误C4700:使用了未初始化的局部变量'i'
在GCC中,如果您打开所有警告,则会收到以下消息:
错误:引用'i'本身已初始化[-Werror = init-self]
但是如果您没有打开警告,它会默默地编译并执行错误的操作
答案 1 :(得分:0)
您可以通过在阴影之前创建对外部变量的引用来访问外部变量:
int main()
{
int i = 10;
if (1)
{
int &main_i = i;
int i = 5;
std::cout << "Local i: " << i << std::endl;
std::cout << "Main's i: " << main_i << std::endl;
}
return 0;
}
答案 2 :(得分:0)
否,您不能使用:: resolution运算符来封闭范围。 '::'运算符既可以用作一元也可以用作二进制。如果名称空间作用域或全局作用域名称被块或类中的等效名称的特定声明隐藏,则可以使用一元作用域运算符。例如-
#include <iostream>
using namespace std;
int tVar = 0;
int main(void) {
int tVar = 0;
::tVar = 5; // set global tVar to 5
tVar = 6; // set local tVar to 6
cout << ::tVar << ", " << tVar;
return 0;
}
您已经提到和::的二进制用例。此外,了解C ++块可能会对本文有所帮助-http://www.ccplusplus.com/2011/08/scope-of-identifiers-in-c.html