Skip to content

C++ 变量作用域

变量的作用域是指变量在程序中可以被访问的区域。理解作用域对于编写正确、可维护的 C++ 程序至关重要。

1. 作用域的类型

C++ 中主要有以下几种作用域:

  1. 局部作用域(Local Scope)
  2. 全局作用域(Global Scope)
  3. 类作用域(Class Scope)
  4. 命名空间作用域(Namespace Scope)
  5. 函数作用域(Function Scope)
  6. 块作用域(Block Scope)

2. 局部作用域

在函数或代码块内部声明的变量具有局部作用域,只能在声明它的函数或代码块中访问。

2.1 局部变量

cpp
#include <iostream>

void function() {
    int local_var = 10;  // 局部变量
    std::cout << "局部变量: " << local_var << std::endl;
}

int main() {
    function();
    // std::cout << local_var << std::endl;  // 错误:无法访问
    return 0;
}

2.2 块作用域

在代码块(由花括号{}包围)内部声明的变量具有块作用域:

cpp
#include <iostream>

int main() {
    int a = 10;
    
    {
        int b = 20;  // 块作用域变量
        std::cout << "a = " << a << ", b = " << b << std::endl;
    }
    
    std::cout << "a = " << a << std::endl;
    // std::cout << "b = " << b << std::endl;  // 错误:b 超出作用域
    
    return 0;
}

3. 全局作用域

在所有函数外部声明的变量具有全局作用域,可以在整个程序中访问。

3.1 全局变量

cpp
#include <iostream>

int global_var = 100;  // 全局变量

void function1() {
    std::cout << "函数1中的全局变量: " << global_var << std::endl;
}

void function2() {
    std::cout << "函数2中的全局变量: " << global_var << std::endl;
}

int main() {
    std::cout << "main函数中的全局变量: " << global_var << std::endl;
    function1();
    function2();
    return 0;
}

3.2 全局变量的初始化

全局变量在程序启动时初始化,如果没有显式初始化,则自动初始化为 0:

cpp
int initialized_var = 10;    // 显式初始化
int uninitialized_var;      // 自动初始化为 0

int main() {
    std::cout << initialized_var << std::endl;      // 输出: 10
    std::cout << uninitialized_var << std::endl;    // 输出: 0
    return 0;
}

4. 类作用域

在类内部声明的成员变量和成员函数具有类作用域,可以通过类的对象或指针访问。

4.1 成员变量

cpp
#include <iostream>
#include <string>

class Student {
private:
    std::string name;  // 私有成员变量
    int age;           // 私有成员变量

public:
    Student(std::string n, int a) : name(n), age(a) {}
    
    void print() {
        std::cout << "姓名: " << name << ", 年龄: " << age << std::endl;
    }
};

int main() {
    Student student("张三", 20);
    student.print();
    // std::cout << student.name << std::endl;  // 错误:私有成员无法直接访问
    return 0;
}

5. 命名空间作用域

在命名空间内部声明的变量和函数具有命名空间作用域,可以通过命名空间限定符访问。

5.1 命名空间

cpp
#include <iostream>

namespace MyNamespace {
    int value = 100;
    
    void print() {
        std::cout << "命名空间中的值: " << value << std::endl;
    }
}

int main() {
    // 使用命名空间限定符
    std::cout << MyNamespace::value << std::endl;
    MyNamespace::print();
    
    // 使用 using 声明
    using MyNamespace::value;
    std::cout << value << std::endl;
    
    // 使用 using 指令
    using namespace MyNamespace;
    print();
    
    return 0;
}

6. 函数作用域

在函数内部声明的变量具有函数作用域,只能在函数内部访问。这与局部作用域类似。

6.1 函数参数

函数参数也具有函数作用域:

cpp
#include <iostream>

void function(int param) {
    std::cout << "参数: " << param << std::endl;
    // std::cout << param << std::endl;  // 可以访问
}

int main() {
    function(10);
    // std::cout << param << std::endl;  // 错误:无法访问
    return 0;
}

7. 作用域解析运算符

作用域解析运算符::用于访问全局变量或命名空间中的成员。

7.1 访问全局变量

当局部变量与全局变量同名时,可以使用::访问全局变量:

cpp
#include <iostream>

int value = 100;  // 全局变量

int main() {
    int value = 200;  // 局部变量
    std::cout << "局部变量: " << value << std::endl;        // 输出: 200
    std::cout << "全局变量: " << ::value << std::endl;    // 输出: 100
    return 0;
}

8. 静态局部变量

使用static关键字声明的局部变量具有静态存储持续时间,只在第一次声明时初始化,之后保持其值。

8.1 静态局部变量的特性

cpp
#include <iostream>

void counter() {
    static int count = 0;  // 静态局部变量
    count++;
    std::cout << "计数: " << count << std::endl;
}

int main() {
    counter();  // 输出: 计数: 1
    counter();  // 输出: 计数: 2
    counter();  // 输出: 计数: 3
    return 0;
}

9. 变量的隐藏

当内部作用域的变量与外部作用域的变量同名时,内部作用域的变量会隐藏外部作用域的变量。

9.1 变量隐藏示例

cpp
#include <iostream>

int value = 100;  // 全局变量

int main() {
    int value = 200;  // 局部变量隐藏全局变量
    
    {
        int value = 300;  // 块作用域变量隐藏局部变量
        std::cout << "块作用域变量: " << value << std::endl;  // 输出: 300
    }
    
    std::cout << "局部变量: " << value << std::endl;  // 输出: 200
    std::cout << "全局变量: " << ::value << std::endl;  // 输出: 100
    
    return 0;
}

10. 外部变量

使用extern关键字可以在一个文件中声明另一个文件中定义的全局变量。

10.1 外部变量示例

cpp
// file1.cpp
int global_var = 100;

// file2.cpp
#include <iostream>

extern int global_var;  // 声明外部变量

int main() {
    std::cout << global_var << std::endl;  // 输出: 100
    return 0;
}

11. 命名空间与作用域

命名空间提供了一种组织代码的方式,避免命名冲突。

11.1 嵌套命名空间

cpp
#include <iostream>

namespace Outer {
    int value1 = 100;
    
    namespace Inner {
        int value2 = 200;
    }
}

int main() {
    std::cout << Outer::value1 << std::endl;           // 输出: 100
    std::cout << Outer::Inner::value2 << std::endl;    // 输出: 200
    return 0;
}

12. 示例:综合运用

现在,让我们看一个综合运用各种作用域的例子:

cpp
#include <iostream>

// 全局变量
int global_var = 100;
const int MAX_VALUE = 1000;

// 命名空间
namespace Math {
    const double PI = 3.14159;
    
    double calculate_area(double radius) {
        return PI * radius * radius;
    }
}

// 类
class Counter {
private:
    static int count;  // 静态成员变量

public:
    static void increment() {
        count++;
    }
    
    static void print() {
        std::cout << "计数: " << count << std::endl;
    }
};

// 初始化静态成员变量
int Counter::count = 0;

// 函数
void demonstrate_scope() {
    int local_var = 10;
    static int static_var = 0;
    
    std::cout << "局部变量: " << local_var << std::endl;
    std::cout << "静态局部变量: " << static_var << std::endl;
    std::cout << "全局变量: " << global_var << std::endl;
    
    static_var++;
    global_var++;
    
    {
        int block_var = 20;
        std::cout << "块作用域变量: " << block_var << std::endl;
    }
    
    // std::cout << block_var << std::endl;  // 错误:超出作用域
}

int main() {
    // 演示作用域
    demonstrate_scope();
    demonstrate_scope();
    
    std::cout << "\n全局变量: " << global_var << std::endl;
    
    // 演示命名空间
    std::cout << "\n圆周率: " << Math::PI << std::endl;
    std::cout << "圆的面积: " << Math::calculate_area(5.0) << std::endl;
    
    // 演示静态成员变量
    std::cout << "\n静态成员变量:" << std::endl;
    Counter::increment();
    Counter::increment();
    Counter::print();
    
    // 演示变量隐藏
    int global_var = 200;
    std::cout << "\n局部变量: " << global_var << std::endl;
    std::cout << "全局变量: " << ::global_var << std::endl;
    
    return 0;
}

小结

C++ 变量作用域包括:

  1. 局部作用域:在函数或代码块内部声明的变量
  2. 全局作用域:在所有函数外部声明的变量
  3. 类作用域:在类内部声明的成员变量和成员函数
  4. 命名空间作用域:在命名空间内部声明的变量和函数
  5. 函数作用域:函数参数具有函数作用域
  6. 块作用域:在代码块内部声明的变量

关键概念:

  • 作用域解析运算符::用于访问全局变量或命名空间中的成员
  • 静态局部变量:使用static关键字声明,只在第一次声明时初始化
  • 变量隐藏:内部作用域的变量会隐藏外部作用域的同名变量
  • 外部变量:使用extern关键字声明在其他文件中定义的全局变量

理解作用域对于编写正确、可维护的 C++ 程序至关重要。在后续章节中,我们将学习 C++ 的常量和修饰符类型。