3. Definicje zmiennych i ich zasięg

3.1. Zasięg widoczności

W poprzednim rozdziale wspomniałem o „dostępności zmiennej w kontekście” … hem … a co to znaczy?

W C++ każda nazwa może być wykorzystywana jedynie w tej części programu, gdzie jest znana. Wszędzie znane są jedynie nazwy (identyfikatory) zdefiniowane w przestrzeni globalnej, ciągle przy zastrzeżeniu obowiązywania zasady predeklaracji.

Ogólne zasady widoczności można streścić następująco:

  • nazwy globalne są widoczne od miejsca deklaracji do końca pliku. Globalnie widoczne są nazwy deklarowane poza funkcją, klasą i przestrzenią nazw,
  • nazwy lokalne są widoczne wewnątrz bloku { },
  • nazwy z przestrzeni nazw są widoczne wewnątrz tej przestrzeni,
  • nazwy należące do klasy są widoczne wewnątrz klasy.

Kompilator C++ czyta plik z kodem od góry do dołu. Każdą napotkaną nazwę (identyfikator) próbuje rozszyfrować korzystając kolejno z lokalnej przestrzeni nazw, następnie z klasy, klas podstawowych dla danej klasy, przestrzeni nazw bieżących i podstawowych, oraz przestrzeni globalnej – i przestaje szukać po znalezieniu pierwszego dopasowania.

Z takiego cyklu działania wynika kolejny mechanizm: przysłaniania nazw. Każda nazwa może być wykorzystana tylko raz – ale w jednej przestrzeni nazw. Postawienie nawiasów klamrowych otwiera nową przestrzeń nazw. Popatrzcie na poniższy kod:


int x; // x zasięg nazw globalny

int main(int argc, char *argv[])
{
  // x w zasięgu nazw funkcji main – inna zmienna niż globalne x
  int x = 1;
  {
    // x w zasięgu nazw wewnętrznym – inne niż dwa dotychczasowe x
    int x = 2;
    cout << x << endl;

    // odwołanie do globalnego x
    ::x = x + 2;
  }
  cout << x << endl;

  cout << ::x << endl;

  {
    // tej linii nie da się wykonać – definicja x przykryła x z main
    int x = x;
  }
}

void f()
{
  int y = x; // globalne x
  int x = 22; // lokalne x
  y = x; // lokalne x
}

Nazwa x jest wykorzystywana wielokrotnie, przy czym w zależności od kontekstu - wskazuje na różne zmienne...