范围 (C++)
声明类、函数或变量等程序元素时,其名称只能在程序的某些部分“查看”和使用。 名称可见的上下文称为其范围。 例如,如果在函数中声明变量 x
,则 x
仅在该函数正文中可见。 它具有局部范围。 程序中可能存在具有相同名称的其他变量;只要它们位于不同的范围,就不会违反“一个定义规则”,也不会引发任何错误。
对于自动非静态变量,范围还确定它们在程序内存中创建和销毁的时间。
有六种范围:
全局范围,全局名称是在任何类、函数或命名空间之外声明的名称。 但是,在 C++ 中,即使是这些名称也具有隐式全局命名空间。 全局名称的范围从声明点扩展到声明文件末尾。 对于全局名称,可见性也受链接规则的约束,这些规则确定名称是否在程序中的其他文件中可见。
命名空间范围,在命名空间中声明的名称(在任何类或枚举定义或函数块之外)从其声明点到命名空间末尾可见。 命名空间可以在跨不同文件的多个块中定义。
局部范围,在函数或 lambda 中声明的名称(包括参数名称)具有局部范围。 它们通常被称为“局部变量”。 它们仅从声明点到函数或 lambda 正文的末尾可见。 局部范围是一种块范围,本文稍后将对此进行讨论。
类范围,类成员的名称具有类范围,该范围在整个类定义中扩展,与声明点无关。 类成员可访问性由
public
、private
和protected
关键字进一步控制。 只能使用成员选择运算符(. 或 ->)或指向成员的指针运算符(.* or ->*)访问公共或受保护成员。语句范围,在
for
、if
、while
或switch
语句中声明的名称在语句块结束之前可见。函数范围,标签具有函数范围,这意味着它在整个函数正文中甚至在声明点之前都是可见的。 函数范围允许在声明
cleanup
标签之前编写goto cleanup
等语句。
隐藏名称
可通过在封闭块中声明名称来隐藏该名称。 在下图中,在内部块中重新声明 i
,从而隐藏与外部块范围中的 i
关联的变量。
块范围和名称隐藏
来自图中显示的程序的输出为:
i = 0
i = 7
j = 9
i = 0
注意
自变量 szWhat
被视为处于函数的范围内。 因此,它被当做就像已在函数的最外层块中声明一样。
隐藏类名
通过声明同一范围内的函数、对象或变量或枚举器,可以隐藏类名称。 但是,在关键字 class
作为前缀时仍可以访问类名称。
// hiding_class_names.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
// Declare class Account at global scope.
class Account
{
public:
Account( double InitialBalance )
{ balance = InitialBalance; }
double GetBalance()
{ return balance; }
private:
double balance;
};
double Account = 15.37; // Hides class name Account
int main()
{
class Account Checking( Account ); // Qualifies Account as
// class name
cout << "Opening account with a balance of: "
<< Checking.GetBalance() << "\n";
}
//Output: Opening account with a balance of: 15.37
注意
在任何位置调用类名称 (Account
),关键字类都必须用于将其与全局范围内的变量 Account 区分开来。 当类名出现在范围解析运算符 (::) 的左侧时,此规则不适用。 在范围解析运算符的左侧的名称始终被视为类名称。
下面的示例演示如何使用 class
关键字声明指向类型 Account
的对象的指针:
class Account *Checking = new class Account( Account );
前面的语句中的初始值设定项(括号内)的 Account
具有全局范围;它的类型为 double
。
注意
此示例中所示的标识符名称的重用被视为较差的编程样式。
有关类对象的声明和初始化的信息,请参阅类、结构和联合。 有关使用 new
和 delete
自由存储运算符的信息,请参阅new 和 delete 运算符。
隐藏具有全局范围的名称
通过在块范围中显式声明相同的名称,可以隐藏带全局范围的名称。 但是,可以使用范围解析运算符 (::
) 访问全局范围名称。
#include <iostream>
int i = 7; // i has global scope, outside all blocks
using namespace std;
int main( int argc, char *argv[] ) {
int i = 5; // i has block scope, hides i at global scope
cout << "Block-scoped i has the value: " << i << "\n";
cout << "Global-scoped i has the value: " << ::i << "\n";
}
Block-scoped i has the value: 5
Global-scoped i has the value: 7
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈