Zasłanianie nazw (ang. name hiding) w C++ to sytuacja, w której zmienna, funkcja lub inny obiekt lokalny o tej samej nazwie jak obiekt globalny lub zewnętrzny przysłania (zasłania) dostęp do tego obiektu. Może to prowadzić do niezamierzonych skutków, ponieważ obiekt lokalny będzie używany zamiast globalnego. Dlatego ważne jest, aby zrozumieć, jak działa zasłanianie nazw i jak je rozwiązać.
Zasłanianie nazw w C++ występuje najczęściej, gdy używamy zmiennych lokalnych w funkcjach lub blokach kodu, które mają takie same nazwy jak zmienne globalne. Aby lepiej zrozumieć, zobaczymy to na prostym przykładzie.
Przykład kodu – Zasłanianie nazw w C++
Utwórz nowy plik o nazwie name_hiding.cpp
i skopiuj do niego poniższy kod:
#include <iostream>
// Deklarujemy zmienną globalną
int number = 10;
int main() {
// Wyświetlamy wartość zmiennej globalnej
std::cout << "Wartość zmiennej globalnej: " << number << std::endl;
// Rozpoczynamy blok kodu
{
// Deklarujemy zmienną lokalną o tej samej nazwie jak zmienna globalna
int number = 20;
// Wewnątrz tego bloku zmienna lokalna zasłania zmienną globalną
std::cout << "Wartość zmiennej lokalnej w bloku: " << number << std::endl;
}
// Wyświetlamy wartość zmiennej globalnej po wyjściu z bloku
std::cout << "Wartość zmiennej globalnej po wyjściu z bloku: " << number << std::endl;
// Deklarujemy zmienną lokalną o tej samej nazwie w funkcji main
int number = 30;
// Teraz zmienna lokalna w funkcji main zasłania zmienną globalną
std::cout << "Wartość zmiennej lokalnej w funkcji main: " << number << std::endl;
// Odwołanie się do zmiennej globalnej przy użyciu operatora zasięgu (::)
std::cout << "Wartość zmiennej globalnej (używając ::): " << ::number << std::endl;
return 0;
}
Jak działa program
W tym programie mamy zmienną globalną number
, która ma wartość 10
. Wewnątrz funkcji main
oraz w bloku kodu deklarujemy zmienne lokalne o tej samej nazwie, co zmienna globalna. W rezultacie zmienne lokalne zasłaniają zmienną globalną, a kiedy odwołujemy się do nazwy number
w obrębie lokalnego zakresu, uzyskujemy dostęp do zmiennej lokalnej, a nie globalnej. Jednak możemy uzyskać dostęp do zmiennej globalnej, używając operatora zasięgu ::
.
Opisy w kodzie
- Deklaracja zmiennej globalnej:
int number = 10;
– Zmienna globalnanumber
jest dostępna w całym programie, poza blokami kodu i funkcjami, które mają lokalne zmienne o tej samej nazwie.
- Wyświetlanie zmiennej globalnej:
std::cout << "Wartość zmiennej globalnej: " << number << std::endl;
– Tutaj wyświetlamy wartość zmiennej globalnejnumber
.
- Blok kodu:
- Wewnątrz nawiasów
{ ... }
zaczyna się nowy blok kodu. Zmienna lokalna o nazwienumber
jest zadeklarowana w tym bloku i przyjmuje wartość20
. int number = 20;
– Zmienna lokalna zasłania zmienną globalną o tej samej nazwie. Wewnątrz tego bloku każdorazowe użycienumber
odnosi się do zmiennej lokalnej.std::cout << "Wartość zmiennej lokalnej w bloku: " << number << std::endl;
– Wypisuje wartość zmiennej lokalnej w tym bloku kodu, czyli20
.
- Wewnątrz nawiasów
- Wyjście z bloku:
- Po zakończeniu bloku zmienna lokalna zostaje zniszczona, a dostęp do zmiennej globalnej zostaje przywrócony.
std::cout << "Wartość zmiennej globalnej po wyjściu z bloku: " << number << std::endl;
– Wyświetla wartość zmiennej globalnej, która ponownie jest widoczna i ma wartość10
.
- Zmienna lokalna w funkcji
main
:int number = 30;
– Tutaj deklarujemy zmienną lokalnąnumber
w funkcjimain
. Ta zmienna teraz zasłania zmienną globalną.std::cout << "Wartość zmiennej lokalnej w funkcji main: " << number << std::endl;
– Wyświetla wartość nowo zadeklarowanej zmiennej lokalnejnumber
, czyli30
.
- Dostęp do zmiennej globalnej przy użyciu operatora zasięgu:
std::cout << "Wartość zmiennej globalnej (używając ::): " << ::number << std::endl;
– Operator::
pozwala na dostęp do zmiennej globalnejnumber
, mimo że w lokalnym zasięgu jest zasłonięta przez zmienną lokalną. Dzięki temu możemy zobaczyć, że wartość zmiennej globalnej wynosi nadal10
.
Podsumowanie
W tej lekcji dowiedziałeś się, czym jest zasłanianie nazw w C++. Zmienna lokalna o tej samej nazwie, co zmienna globalna, zasłania ją w swoim zakresie, a użycie nazwy zmiennej odnosi się do zmiennej lokalnej. Aby odwołać się do zmiennej globalnej, można użyć operatora zasięgu ::
.
Zasłanianie nazw może prowadzić do błędów i trudności w zrozumieniu kodu, dlatego warto unikać używania takich samych nazw dla zmiennych w różnych zakresach.