Udostępnij za pośrednictwem


Zakres (C++)

W przypadku deklarowania elementu programu, takiego jak klasa, funkcja lub zmienna, jego nazwa może być widoczna tylko w niektórych częściach programu. Kontekst, w którym jest widoczna nazwa, jest nazywany jego zakresem. Jeśli na przykład zadeklarujesz zmienną x w funkcji, x będzie widoczna tylko w tej treści funkcji. Ma on zakres lokalny. Możesz mieć inne zmienne o tej samej nazwie w programie; o ile znajdują się one w różnych zakresach, nie naruszają reguły jednej definicji i nie są zgłaszane żadne błędy.

W przypadku automatycznych zmiennych niestacjonanych zakres określa również, kiedy są tworzone i niszczone w pamięci programu.

Istnieje sześć rodzajów zakresu:

  • Zakres globalny Nazwa globalna to nazwa zadeklarowana poza dowolną klasą, funkcją lub przestrzenią nazw. Jednak w języku C++ nawet te nazwy istnieją z niejawną globalną przestrzenią nazw. Zakres nazw globalnych rozciąga się od punktu deklaracji na koniec pliku, w którym są deklarowane. W przypadku nazw globalnych widoczność podlega również regułom łączenia , które określają, czy nazwa jest widoczna w innych plikach w programie.

  • Zakres przestrzeni nazw Nazwa zadeklarowana w przestrzeni nazw poza dowolną definicją klasy lub definicją wyliczenia lub blokiem funkcji jest widoczna z punktu deklaracji na końcu przestrzeni nazw. Przestrzeń nazw może być zdefiniowana w wielu blokach w różnych plikach.

  • Zakres lokalny Nazwa zadeklarowana w funkcji lub lambda, w tym nazwy parametrów, mają zakres lokalny. Są one często określane jako "lokalne". Są one widoczne tylko z punktu deklaracji na końcu funkcji lub treści lambda. Zakres lokalny jest rodzajem zakresu blokowego, który został omówiony w dalszej części tego artykułu.

  • Nazwy zakresów klas składowych klasy mają zakres klas, który rozciąga się w całej definicji klasy niezależnie od punktu deklaracji. Ułatwienia dostępu składowych klasy są dodatkowo kontrolowane przez publicsłowa kluczowe , privatei protected . Dostęp do publicznych lub chronionych elementów członkowskich można uzyskać tylko za pomocą operatorów wyboru składowych (. lub ->) lub operatorów wskaźnika do składowych (.* lub -).>*

  • Nazwy zakresu instrukcji zadeklarowane w instrukcji for, if, whilelub switch są widoczne do końca bloku instrukcji.

  • Zakres funkcji Etykietafunkcji ma zakres funkcji, co oznacza, że jest widoczny w całej treści funkcji jeszcze przed jego punktem deklaracji. Zakres funkcji umożliwia pisanie instrukcji, takich jak goto cleanup przed zadeklarowaną etykietą cleanup .

Ukrywanie nazw

Nazwę można ukryć, deklarując ją w zamkniętym bloku. Na poniższej ilustracji i element jest ponownie zadeklarowany w bloku wewnętrznym, ukrywając w ten sposób zmienną skojarzona z i zakresem bloku zewnętrznego.

Diagram that shows block scope name hiding.
Blokuj ukrywanie zakresu i nazwy

Dane wyjściowe programu pokazane na rysunku to:

i = 0
i = 7
j = 9
i = 0

Uwaga

Argument szWhat jest uważany za w zakresie funkcji. W związku z tym jest traktowana tak, jakby została zadeklarowana w najbardziej zewnętrznym bloku funkcji.

Ukrywanie nazw klas

Nazwy klas można ukryć, deklarując funkcję, obiekt lub zmienną albo moduł wyliczający w tym samym zakresie. Jednak nazwa klasy nadal może być dostępna po prefiksie słowa kluczowego class.

// hiding_class_names.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;

// Declare class Account at global scope.
class Account
{
public:
    Account( double InitialBalance )
        { balance = InitialBalance; }
    double GetBalance()
        { return balance; }
private:
    double balance;
};

double Account = 15.37;            // Hides class name Account

int main()
{
    class Account Checking( Account ); // Qualifies Account as
                                       //  class name

    cout << "Opening account with a balance of: "
         << Checking.GetBalance() << "\n";
}
//Output: Opening account with a balance of: 15.37

Uwaga

Każde miejsce, dla którego jest wywoływana nazwa klasy (Account), należy użyć klasy słowa kluczowego, aby odróżnić ją od konta zmiennej o zakresie globalnym. Ta reguła nie ma zastosowania, gdy nazwa klasy występuje po lewej stronie operatora rozpoznawania zakresu (::). Nazwy po lewej stronie operatora rozpoznawania zakresu są zawsze uznawane za nazwy klas.

W poniższym przykładzie pokazano, jak zadeklarować wskaźnik do obiektu typu Account przy użyciu słowa kluczowego class :

class Account *Checking = new class Account( Account );

Inicjator Account (w nawiasach) w poprzedniej instrukcji ma zakres globalny; jest doubletypu .

Uwaga

Ponowne użycie nazw identyfikatorów, jak pokazano w tym przykładzie, jest uznawane za słaby styl programowania.

Aby uzyskać informacje o deklarowaniu i inicjowaniu obiektów klasy, zobacz Klasy, struktury i unii. Aby uzyskać informacje o korzystaniu z new operatorów magazynu i delete , zobacz operatory nowych i usuwania.

Ukrywanie nazw przy użyciu zakresu globalnego

Nazwy z zakresem globalnym można ukryć, jawnie deklarując tę samą nazwę w zakresie bloku. Można jednak uzyskać dostęp do nazw zakresów globalnych przy użyciu operatora rozpoznawania zakresu (::).

#include <iostream>

int i = 7;   // i has global scope, outside all blocks
using namespace std;

int main( int argc, char *argv[] ) {
   int i = 5;   // i has block scope, hides i at global scope
   cout << "Block-scoped i has the value: " << i << "\n";
   cout << "Global-scoped i has the value: " << ::i << "\n";
}
Block-scoped i has the value: 5
Global-scoped i has the value: 7

Zobacz też

Podstawowe pojęcia