Mỗi khối xác định vùng phạm vi riêng của nó. Vậy điều gì sẽ xảy ra khi chúng ta có một biến bên trong một khối lồng nhau có cùng tên với một biến trong một khối bên ngoài? Khi điều này xảy ra, biến lồng nhau “ẩn” với biến bên ngoài trong các khu vực mà cả hai đều nằm trong phạm vi đó. Đây được gọi là ẩn tên hoặc che bóng.

1. Ẩn tên các biến cục bộ

/*
Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
@author cafedevn
Contact: cafedevn@gmail.com
Fanpage: https://www.facebook.com/cafedevn
Group: https://www.facebook.com/groups/cafedev.vn/
Instagram: https://instagram.com/cafedevn
Twitter: https://twitter.com/CafedeVn
Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
Pinterest: https://www.pinterest.com/cafedevvn/
YouTube: https://www.youtube.com/channel/UCE7zpY_SlHGEgo67pHxqIoA/
*/

#include <iostream>
 
int main()
{ // outer block
    int apples { 5 }; // here's the outer block apples
 
    { // nested block
        // apples refers to outer block apples here
        std::cout << apples << '\n'; // print value of outer block apples
 
        int apples{ 0 }; // define apples in the scope of the nested block
 
        // apples now refers to the nested block apples
        // the outer block apples is temporarily hidden
 
        apples = 10; // this assigns value 10 to nested block apples, not outer block apples
 
        std::cout << apples << '\n'; // print value of nested block apples
    } // nested block apples destroyed
 
 
    std::cout << apples << '\n'; // prints value of outer block apples
 
    return 0;
} // outer block apples destroyed

Nếu bạn chạy chương trình này, nó sẽ in:

5
10
5

Trong chương trình trên, đầu tiên chúng ta khai báo một biến có tên là táo trong khối bên ngoài. Biến này có thể nhìn thấy trong khối bên trong, mà chúng ta có thể thấy bằng cách in giá trị của nó (5). Sau đó, chúng ta khai báo một biến khác (cũng có tên là apple) trong khối lồng nhau. Từ thời điểm này đến cuối khối, tên gọi apple dùng để chỉ những quả táo khối lồng nhau, không phải những quả táo khối bên ngoài.

Do đó, khi chúng ta gán giá trị 10 cho các apple, chúng ta đang gán giá trị đó cho các apple khối lồng nhau. Sau khi in giá trị này (10), các apple khối lồng nhau sẽ bị phá hủy. Sự tồn tại và giá trị của apple khối bên ngoài không bị ảnh hưởng và chúng ta chứng minh điều này bằng cách in giá trị của apple khối bên ngoài (5).

Lưu ý rằng nếu các apple  khối lồng nhau chưa được khai báo, tên apple trong khối lồng nhau sẽ vẫn đề cập đến các apple khối bên ngoài, do đó, việc gán giá trị 10 cho các apple sẽ được áp dụng cho các apple khối bên ngoài:

#include <iostream>
 
int main()
{ // outer block
    int apples{5}; // here's the outer block apples
 
    { // nested block
        // apples refers to outer block apples here
        std::cout << apples << '\n'; // print value of outer block apples
 
        // no inner block apples defined in this example
 
        apples = 10; // this applies to outer block apples
 
        std::cout << apples << '\n'; // print value of outer block apples
    } // outer block apples retains its value even after we leave the nested block
 
    std::cout << apples << '\n'; // prints value of outer block apples
 
    return 0;
} // outer block apples destroyed

Kết quả

5
10
10

Khi ở bên trong khối lồng nhau, không có cách nào để truy cập trực tiếp vào biến ẩn từ khối bên ngoài.

2. Ẩn tên các biến toàn cục

Tương tự như cách các biến trong một khối lồng nhau có thể ẩn các biến trong một khối bên ngoài, các biến cục bộ có cùng tên với biến toàn cục sẽ tạo ẩn tên cho biến toàn cục ở bất cứ nơi nào biến cục bộ nằm trong cùng phạm vi:

#include <iostream>
int value { 5 }; // global variable
 
void foo()
{
    std::cout << "global variable value: " << value << '\n'; // value is not shadowed here, so this refers to the global value
}
 
int main()
{
    int value { 7 }; // hides the global variable value until the end of this block
 
    ++value; // increments local value, not global value
 
    std::cout << "local variable value: " << value << '\n';
 
    foo();
 
    return 0;
} // local value is destroyed

Kết quả:

local variable value: 8
global variable value: 5

Tuy nhiên, vì các biến toàn cục là một phần của không gian tên toàn cục, chúng ta có thể sử dụng toán tử phạm vi (: 🙂 không có tiền tố để cho trình biên dịch biết chúng ta dùng biến toàn cục thay vì biến cục bộ.

#include <iostream>
int value { 5 }; // global variable
 
int main()
{
    int value { 7 }; // hides the global variable value
    ++value; // increments local value, not global value
 
    --(::value); // decrements global value, not local value (parenthesis added for readability)
 
    std::cout << "local variable value: " << value << '\n';
    std::cout << "global variable value: " << ::value << '\n';
 
    return 0;
} // local value is destroyed

Kết quả

local variable value: 8
global variable value: 4

3. Tránh biến ẩn tên

Nói chung nên tránh việc che khuất các biến cục bộ, vì nó có thể dẫn đến các lỗi vô ý khi biến sai được sử dụng hoặc sửa đổi. Một số trình biên dịch sẽ đưa ra cảnh báo khi một biến bị ẩn.

Vì lý do tương tự mà chúng ta khuyên bạn nên tránh ẩn các biến cục bộ, chúng ta cũng khuyên bạn nên tránh ẩn các biến toàn cục. Điều này có thể tránh được nếu tất cả các tên chung của bạn sử dụng tiền tố “g_”.

Cài ứng dụng cafedev để dễ dàng cập nhật tin và học lập trình mọi lúc mọi nơi tại đây.

Nguồn và Tài liệu tiếng anh tham khảo:

Tài liệu từ cafedev:

Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:

Chào thân ái và quyết thắng!

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!