C/C++ programming: scope

  • Every name that appears in a C++ program is only valid in some parts of the source code that may not be continuous, and these parts are called its scope

  • Within the scope, you can use 无限定名字查找to associate the name with its declaration

Block scope

int main()
{
    
    
    int a = 0; // 第一个 'a' 的作用域开始
    ++a; // 名字 'a' 在作用域中并指代第一个 'a'
    {
    
    
        int a = 1; // 第二个 'a' 的作用域开始
                   // 第一个 'a' 的作用域间断
        a = 42;    // 'a' 在作用域中并指代第二个 'a'
    } // 块结束,第二个 'a' 的作用域结束
      //        第一个 'a' 的作用域恢复
} // 块结束,第一个 'a' 的作用域结束
int b = a; // 错误:名字 'a' 不在作用域中
try {
    
       
    f();
} catch(const std::runtime_error& re) {
    
     // re 的作用域开始
    int n = 1; // n 的作用开始
    std::cout << re.what(); // re 在作用域中
} // re 的作用域结束, n 的作用域结束
 catch(std::exception& e) {
    
    
    std::cout << re.what(); // 错误: re 不在作用域中
    ++n; // 错误: n 不在作用域中
}
Base* bp = new Derived;
if(Derived* dp = dynamic_cast<Derived*>(bp))
{
    
    
    dp->f(); // dp 在作用域中
} // dp 的作用域结束
 
for(int n = 0; // n 的作用域开始
    n < 10;    // n 在作用域中
    ++n)       // n 在作用域中
{
    
    
    std::cout << n << ' '; // n 在作用域中
} // n 的作用域结束

Function parameter scope

const int n = 3;
 
int f1(int n,     // 全局 'n' 的作用域间断
                  // 形参 'n' 的作用域开始
       int y = n); // 错误:默认实参涉指了形参
 
int (*(*f2)(int n))[n]; // OK :函数形参 'n' 的作用域终止于其函数声明符的末尾
                        // 在数组声明符中,全局 n 在作用域中
// (这声明了一个返回(含有 3 个 int 元素的数组的指针)的函数的指针)
 
// 相反
auto (*f3)(int n)->int (*)[n]; // 错误:以形参 'n' 为数组边界
 
 
int f(int n = 2)  // 'n' 的作用域开始
try // 函数 try 块
{
    
             // 函数体开始
   ++n;   // 'n' 在作用域中并指代函数形参
   {
    
    
      int n = 2; // 局部变量 'n' 的作用域开始
                 // 函数形参 'n' 的作用域中断
      ++n; // 'n' 在此块中指代局部变量
    }            // 局部变量 'n' 的作用域结束
                 // 函数形参 'n' 的作用域恢复
} catch(...) {
    
    
   ++n; // n 在作用域中并指代函数形参
   throw;
} // 最后异常处理块结束,函数形参 'n' 的作用域结束
int a = n; // OK :全局 'n' 在作用域中

Function scope

void f()
{
    
    
   {
    
       
       goto label; // label 在作用域中,尽管之后才声明
label:;
   }
   goto label; // label 忽略块作用域
}
 
void g()
{
    
    
    goto label; // 错误: g() 中 label 不在作用域中
}

Namespace scope

namespace N {
    
     // N 的作用域开始(作为全局命名空间的成员)
    int i; // i 的作用域开始
    int g(int a) {
    
     return a; } // g 的作用域开始
    int j(); // j 的作用域开始
    void q(); // q 的作用域开始
    namespace {
    
    
        int x; // x 的作用域开始
    } // x 的作用域不结束
    inline namespace inl {
    
     // inl 的作用域开始
      int y; // y 的作用域开始
    } // y 的作用域不结束
} // i、g、j、q、inl、x、y 的作用域间断
 
namespace {
    
    
    int l=1; // l 的作用域开始
} // l 的作用域不结束(它是无名命名空间的成员)
 
namespace N {
    
     // i、g、j、q、inl、x、y 的作用域继续
    int g(char a) {
    
      // 重载 N::g(int)
        return l+a;  // 来自无名命名空间的 l 在作用域中
    }
    // int i; // 错误:重复定义( i 已在作用域中)
    int j(); // OK :允许重复的函数声明
    int j() {
    
     // OK :定义先前声明的 N::j()
        return g(i); // 调用 N::g(int)
    }
    int q(); // 错误: q 已在作用域中并有不同的返回类型
} // i、g、j、q、inl、x、y 的作用域间断
 
int main() {
    
    
    using namespace N; // i、g、j、q、inl、x、y 的作用域恢复
    i = 1; // N::i 在作用域中
    x = 1; // N::(匿名)::x 在作用域中
    y = 1; // N::inl::y 在作用域中
    inl::y = 2; // N::inl 也在作用域中
} // i、g、j、q、inl、x、y 的作用域间断

Class scope

class X {
    
    
    int f(int a = n) {
    
     // 默认实参内的 X::n 在作用域中
         return a*n;   // 函数体内的   X::n 在作用域中
    }
    using r = int;
    r g();
    int i = n*2;   // 初始化器内的 X::n 在作用域中
 
//  int x[n];      // 错误:类体内的 X::n 不在作用域中
    static const int n = 1;
    int x[n];      // OK : 类体内的 X::n 现在在作用域中
};
 
//r X::g() {       // 错误:类外成员函数内的 r 不在作用域中
auto X::g()->r {
    
       // OK :尾随返回类型内的 X::r 在作用域中
    return n;      // 类外成员函数体内的   X::n 在作用域中
}
typedef int c; // ::c
enum {
    
     i = 1 }; // ::i
class X {
    
    
    char v[i]; // 错误:此处 i 指代 ::i,但 X::i 也存在
    int f() {
    
    
         return sizeof(c); // OK :成员函数体内在作用域中的是 X::c 而非 ::c
    }
    char c; // X::c
    enum {
    
     i = 2 }; // X::i
};
 
typedef char* T;
struct Y {
    
    
    T a; // 错误:此处,T 指代 ::T,但 Y::T 也存在
    typedef long T;
    T b;
};

Guess you like

Origin blog.csdn.net/zhizhengguan/article/details/114898766