Share via


范围 (C++)

声明类、函数或变量等程序元素时,其名称只能在程序的某些部分“查看”和使用。 名称可见的上下文称为其范围。 例如,如果在函数中声明变量 x,则 x 仅在该函数正文中可见。 它具有局部范围。 程序中可能存在具有相同名称的其他变量;只要它们位于不同的范围,就不会违反“一个定义规则”,也不会引发任何错误。

对于自动非静态变量,范围还确定它们在程序内存中创建和销毁的时间。

有六种范围:

  • 全局范围,全局名称是在任何类、函数或命名空间之外声明的名称。 但是,在 C++ 中,即使是这些名称也具有隐式全局命名空间。 全局名称的范围从声明点扩展到声明文件末尾。 对于全局名称,可见性也受链接规则的约束,这些规则确定名称是否在程序中的其他文件中可见。

  • 命名空间范围,在命名空间中声明的名称(在任何类或枚举定义或函数块之外)从其声明点到命名空间末尾可见。 命名空间可以在跨不同文件的多个块中定义。

  • 局部范围,在函数或 lambda 中声明的名称(包括参数名称)具有局部范围。 它们通常被称为“局部变量”。 它们仅从声明点到函数或 lambda 正文的末尾可见。 局部范围是一种块范围,本文稍后将对此进行讨论。

  • 类范围,类成员的名称具有类范围,该范围在整个类定义中扩展,与声明点无关。 类成员可访问性由 publicprivateprotected 关键字进一步控制。 只能使用成员选择运算符(.->)或指向成员的指针运算符(.* or ->*)访问公共或受保护成员。

  • 语句范围,在forifwhileswitch 语句中声明的名称在语句块结束之前可见。

  • 函数范围标签具有函数范围,这意味着它在整个函数正文中甚至在声明点之前都是可见的。 函数范围允许在声明 cleanup 标签之前编写 goto cleanup 等语句。

隐藏名称

可通过在封闭块中声明名称来隐藏该名称。 在下图中,在内部块中重新声明 i,从而隐藏与外部块范围中的 i 关联的变量。

Diagram that shows block scope name hiding.
块范围和名称隐藏

来自图中显示的程序的输出为:

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

注意

此示例中所示的标识符名称的重用被视为较差的编程样式。

有关类对象的声明和初始化的信息,请参阅类、结构和联合。 有关使用 newdelete 自由存储运算符的信息,请参阅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

另请参阅

基本概念