Odpowiedzi:
Kiedy piszesz plik realizacji ( .cpp, .cxxitp) kompilator generuje jednostkę tłumaczeniową . To jest plik źródłowy z twojej implementacji plus wszystkie nagłówki #includew nim zawarte.
Powiązanie wewnętrzne odnosi się do wszystkiego tylko w zakresie jednostki tłumaczeniowej .
Zewnętrzne powiązanie odnosi się do rzeczy, które istnieją poza określoną jednostką tłumaczeniową. Innymi słowy, dostępny przez cały program , który jest kombinacją wszystkich jednostek tłumaczeniowych (lub plików obiektowych).
constzmiennych (a także o jej cel) jest tutaj całkowicie pominięte.
Jak powiedział dudewat, zewnętrzne połączenie oznacza, że symbol (funkcja lub zmienna globalna) jest dostępny w całym programie, a wewnętrzne połączenie oznacza, że jest dostępne tylko w jednej jednostce tłumaczeniowej .
Możesz jawnie kontrolować powiązanie symbolu za pomocą słów kluczowych externi static. Jeśli połączenie nie jest określone, wówczas domyślne połączenie jest externdla constsymboli niebędących symbolami i static(wewnętrzne) dla constsymboli.
// in namespace or global scope
int i; // extern by default
const int ci; // static by default
extern const int eci; // explicitly extern
static int si; // explicitly static
// the same goes for functions (but there are no const functions)
int foo(); // extern by default
static int bar(); // explicitly static
Zauważ, że zamiast używać staticwewnętrznego połączenia, lepiej jest używać anonimowych przestrzeni nazw, w których możesz również umieścić classes. Łączenie anonimowych przestrzeni nazw zmieniło się między C ++ 98 i C ++ 11, ale najważniejsze jest to, że są one nieosiągalne dla innych jednostek tłumaczeniowych.
namespace {
int i; // external linkage but unreachable from other translation units.
class invisible_to_others { };
}
extern deklarację w drugim pliku.static. Mówi się, że takie zmienne mają wewnętrzne powiązanie .Rozważ następujący przykład:
void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
int a;
//...
f(a);
//...
f(a);
//...
}
fdeklaruje się fjako funkcję z zewnętrznym łącznikiem (domyślnie). Jego definicja musi zostać podana w dalszej części tego pliku lub w innej jednostce tłumaczeniowej (podanej poniżej).maxjest zdefiniowany jako stała całkowita. Domyślne połączenie dla stałych jest wewnętrzne . Jego powiązanie zostało zmienione na zewnętrzne za pomocą słowa kluczowego extern. Teraz maxmożna uzyskać dostęp do innych plików.njest zdefiniowany jako zmienna całkowita. Domyślne powiązanie dla zmiennych zdefiniowanych poza ciałami funkcji jest zewnętrzne .#include <iostream>
using namespace std;
extern const int max;
extern int n;
static float z = 0.0;
void f(int i)
{
static int nCall = 0;
int a;
//...
nCall++;
n++;
//...
a = max * z;
//...
cout << "f() called " << nCall << " times." << endl;
}
maxjest zadeklarowany jako zewnętrzny link . W maxjakimś pliku musi pojawić się pasująca definicja (z zewnętrznym powiązaniem). (Jak w 1.cpp)njest zadeklarowany jako zewnętrzny link .zjest zdefiniowany jako zmienna globalna z wewnętrznym sprzężeniem .nCallokreśla, nCallże jest zmienną, która zachowuje swoją wartość między wywołaniami funkcji f(). W przeciwieństwie do zmiennych lokalnych z domyślną automatyczną klasą pamięci, nCallbędą inicjowane tylko raz na początku programu, a nie raz dla każdego wywołania f(). Specyfikator klasy pamięci staticwpływa na czas życia zmiennej lokalnej, a nie na jej zakres.Uwaga: słowo kluczowe staticodgrywa podwójną rolę. W przypadku definicji zmiennych globalnych określa powiązanie wewnętrzne . Kiedy jest używany w definicjach zmiennych lokalnych, określa, że czas życia zmiennej ma być czasem trwania programu, a nie czasem trwania funkcji.
Mam nadzieję, że to pomaga!
staticpozwala na leniwe pojedyncze inicjowanie (co może być przydatne, jeśli potrzebujesz obiektu globalnego, ale musisz kontrolować, kiedy jest on budowany z powodu problemów z globalnym porządkiem konstrukcji i nie może dynamicznie przydzielić go używanie newbardziej szczegółowych schematów inicjalizacji może wykraczać poza to, co jest konieczne dla danego obiektu; w konsekwencji jest to głównie problem w systemach wbudowanych korzystających z C ++).
Porozmawiajmy o innym zakresie w „C”
ZAKRES: Zasadniczo to jak długo mogę coś zobaczyć i jak daleko.
Zmienna lokalna: Zakres jest tylko wewnątrz funkcji. Znajduje się w obszarze STOSOWANIA RAM. Co oznacza, że za każdym razem, gdy funkcja jest wywoływana, wszystkie zmienne wchodzące w skład tej funkcji, w tym argumenty funkcji, są tworzone na nowo i niszczone, gdy kontrola wyjdzie z funkcji. (Ponieważ stos jest opróżniany za każdym razem, gdy funkcja powraca)
Zmienna statyczna: zakres tego dotyczy pliku. Jest dostępny w każdym miejscu pliku,
w którym został zadeklarowany. Znajduje się w segmencie danych RAM. Ponieważ można to uzyskać tylko w pliku, a tym samym połączenie wewnętrzne. Każdy
inne pliki nie widzą tej zmiennej. W rzeczywistości słowo kluczowe STATIC jest jedynym sposobem, w jaki możemy wprowadzić pewien poziom danych lub funkcji
ukrywających się w „C”
Zmienna globalna: zakres tego dotyczy całej aplikacji. Jest dostępny z każdego miejsca aplikacji. Zmienne globalne znajdują się również w segmencie DANYCH, ponieważ można uzyskać do nich dostęp w każdym miejscu aplikacji, a tym samym powiązanie zewnętrzne
Domyślnie wszystkie funkcje są globalne. W przypadku, gdy chcesz ukryć niektóre funkcje w pliku z zewnątrz, możesz poprzedzić funkcję statycznym słowem kluczowym. :-)
Zanim zaczniesz mówić o tym pytaniu, lepiej dokładnie znać termin jednostka tłumacząca , program i kilka podstawowych pojęć C ++ (tak naprawdę łączenie jest ogólnie jednym z nich). Musisz także wiedzieć, jaki jest zakres .
Podkreślę kilka kluczowych punktów, zwłaszcza. brakujące w poprzednich odpowiedziach.
Powiązanie jest właściwością nazwy , która jest wprowadzana przez deklarację . Różne nazwy mogą oznaczać ten sam byt (zazwyczaj obiekt lub funkcję). Zatem mówienie o powiązaniu jednostki jest zwykle nonsensem, chyba że masz pewność, że do jednostki będzie odwoływała się tylko unikalna nazwa z niektórych konkretnych deklaracji (zazwyczaj jednak jedna deklaracja).
Zauważ, że obiekt jest bytem, ale zmienna nim nie jest. Mówiąc o powiązaniu zmiennej, w rzeczywistości chodzi o nazwę oznaczonego bytu (wprowadzoną przez określoną deklarację). Połączenie nazwy znajduje się w jednym z trzech: brak połączenia, połączenie wewnętrzne lub połączenie zewnętrzne.
Różne jednostki tłumaczeniowe mogą współdzielić tę samą deklarację poprzez dołączenie nagłówka / pliku źródłowego (tak, to sformułowanie standardu). Możesz więc odwoływać się do tej samej nazwy w różnych jednostkach tłumaczeniowych. Jeśli zadeklarowana nazwa ma powiązanie zewnętrzne, tożsamość encji, do której odnosi się nazwa, jest również wspólna. Jeśli zadeklarowana nazwa ma powiązanie wewnętrzne, ta sama nazwa w różnych jednostkach tłumaczeniowych oznacza różne jednostki, ale można odwoływać się do jednostki w różnych zakresach tej samej jednostki tłumaczeniowej. Jeśli nazwa nie ma powiązania, po prostu nie można skierować obiektu z innych zakresów.
(Ups ... Odkryłem, że to, co wpisałem, było po prostu powtórzeniem standardowego sformułowania ...)
Istnieją również inne mylące punkty, które nie są uwzględnione w specyfikacji języka.
__attribute____declspecZasada powiązania z zakresu nazw constzmiennej jest coś specjalnego (a szczególnie różni się od constobiektu zadeklarowanego w zakresie plików w języku C, który ma również koncepcję powiązania identyfikatorów). Ponieważ ODR jest wymuszony przez C ++, ważne jest, aby zachować nie więcej niż jedną definicję tej samej zmiennej lub funkcji występującą w całym programie, z wyjątkiem inlinefunkcji . Jeśli nie ma takiej specjalnej zasady const, najprostsza deklaracja constzmiennej z inicjalizatorami (np.= xxx ) W nagłówku lub pliku źródłowym (często „plik nagłówka”) zawarta w wielu jednostkach tłumaczeniowych (lub w tej samej jednostce więcej niż jeden raz, choć rzadko) w programie naruszy ODR, co sprawia, że warto go używaćconst zmienna, ponieważ niemożliwe jest zastąpienie niektórych makr obiektowych.
Myślę, że wewnętrzne i zewnętrzne powiązania w C ++ dają jasne i zwięzłe wyjaśnienie:
Jednostka tłumacząca odnosi się do pliku implementacyjnego (.c / .cpp) i wszystkich zawartych w nim plików nagłówkowych (.h / .hpp). Jeśli obiekt lub funkcja w takiej jednostce tłumaczenia ma wewnętrzne połączenie, ten konkretny symbol jest widoczny tylko dla linkera w tej jednostce tłumaczenia. Jeśli obiekt lub funkcja ma powiązanie zewnętrzne, linker może to również zobaczyć podczas przetwarzania innych jednostek tłumaczeniowych. Statyczne słowo kluczowe użyte w globalnej przestrzeni nazw powoduje, że symbol ma wewnętrzne powiązanie. Słowo kluczowe extern powoduje, że symbol ma zewnętrzny link.
Kompilator domyślnie łączy takie symbole, że:
Niestałe zmienne globalne mają domyślnie zewnętrzne połączenie
Stałe zmienne globalne mają domyślnie wewnętrzne połączenie
Funkcje mają domyślnie zewnętrzne połączenie
Połączenie określa, czy identyfikatory o identycznych nazwach odnoszą się do tego samego obiektu, funkcji lub innej jednostki, nawet jeśli identyfikatory te występują w różnych jednostkach tłumaczeniowych. Połączenie identyfikatora zależy od tego, jak zostało zadeklarowane. Istnieją trzy rodzaje powiązań:
Tylko C ++ : możesz również mieć powiązanie między fragmentami kodu C ++ i innych niż C ++, co nazywa się łączeniem języka .
Źródło: IBM Program Linkage
Gruntownie
extern linkage zmienna jest widoczna we wszystkich plikachinternal linkage zmienna jest widoczna w jednym pliku.Wyjaśnij: stałe zmienne domyślnie łączą się wewnętrznie, chyba że zadeklarowano inaczej jako zewnętrzne
external linkageconstzmienna globalna tointernal linkageextern constzmienna globalna toexternal linkageCałkiem niezły materiał o linkowaniu w C ++
http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/
W C ++
Każda zmienna o zasięgu pliku, która nie jest zagnieżdżona w klasie lub funkcji, jest widoczna we wszystkich jednostkach tłumaczeniowych w programie. Nazywa się to łączem zewnętrznym, ponieważ w czasie łączenia nazwa jest widoczna dla łącznika wszędzie, poza jednostką tłumaczeniową.
Zmienne globalne i funkcje zwykłe mają powiązanie zewnętrzne.
Nazwa obiektu statycznego lub funkcji w zakresie pliku jest lokalna dla jednostki tłumaczącej. To się nazywa jako wewnętrzne połączenie
Powiązanie odnosi się tylko do elementów, które mają adresy w czasie łączenia / ładowania; dlatego deklaracje klas i zmienne lokalne nie są powiązane.