[C++] Nazwy statyczne globalne


(Quentin) #1

Witam!

Mam pytanie dotyczące nazw statycznych globalnych. Jeżeli postawimy przed nimi (zmienną czy też funkcją) specyfikator (przed deklaracją):

static

to taka zmienna (lub funkcja) nie będzie znana w innych plikach składających się na 1 program. Ale przecież i bez tego nazwa globalna nie jest znana w innych plikach - przecież ma ona zakres ważności tylko w obrębie tego pliku, gdzie została zadeklarowana ! (Ci co mają Symfonię C++ z 2006 r. mogą to wyraźnie przeczytać na 72 str.). Więc po co w ogóle takie coś :?: Przykładowo, jeżeli będę chciał skompilować taki program: 1_plik.cpp :

#include 

using namespace std;

void funkcja1();

int x;

int main()

{



int x = 4;

cout << x << "\n\n";


funkcja1();


cout << "\n\n\n\n\n\n";

system("pause");

}

2_plik.cpp :

#include 

using namespace std;

void funkcja1()

{

	cout << "funkcja 1 \n\n";

	cout << x; // <--- błąd ! bo 'x' nie jest znane w TYM pliku

}[/code]

To kompilator wyświetli błąd... Więc na jedno wychodzi - po co w ogóle potrzebne jest to 'static' :?:


(Sawyer47) #2

Ale jeśli załączysz jakiś plik, to już będzie znana. Przykład:

// main.cpp

#include "smth.hpp"


int main()

{

	smth();

	return 0;

}

// smth.cpp

#include "smth.hpp"


void smth()

{

}

// smth.hpp

void smth();

// static void smth();

Jeśli nie użyjesz słowa kluczowego static to wszystko będzie działać, jeśli zadeklarujesz funkcję z tym słowem kluczowym nie uda się tego skompilować. g++ rzuca błąd:

smth.hpp:2: error: ‘void smth()’ used but never defined

(Quentin) #3

Ponieważ będzie ona znana tylko w tym pliku smth.hpp , zgadza się :?: No ale taki plik nagłówkowy załącza się do plików *.cpp, więc dodanie tam static (w pliku *.h ), będzie równoznaczne z:

// void smth();

Co prawda jeżeli był by tam specyfikator static, to funkcja była by znana tylko w pliku nagłówkowym - ale znowu tam nie ma, żadnych instrukcji, więc nie będzie też wywołań funkcji, ponieważ w tych plikach są same deklaracje - nazw, funkcji itp.


([alex]) #4

Wg mnie ten przykład powinien wszystko wyjaśnić:

//plik add.cpp

int NF=999;

static int SF=666;

int rf() { return SF; }

static int srf() { return SF; }

//plik main.cpp

#include 

using namespace std;


int rf();

extern int NF;

int srf(); // nie znajdzie tej srf() z pliku add.cpp ale znajdzie z pliku ext.cpp

extern int SF; // nie znajdzie tej SF z pliku add.cpp ale znajdzie z pliku ext.cpp


int main()

  {

   cout<<"rf()="<
   cout<<"NF="<
   cout<<"srf()="<
   cout<<"SF="<
   cin.get();

   return 0;

  }

//plik ext.cpp

int SF=333;

int srf() { return SF; }

Wszystkie trzy pliki razem, się skompilują i zostanie wygenerowany plik wykonywalny, ale rf zwróci 666, zaś srf zwróci 333.

Jeżeli nie dołączysz plik ext.cpp do projektu, to w wierszach main.cpp oznaczonych "// tu błąd linkera", będzie błąd linkera :lol:

Jeżeli dołączysz plik ext.cpp do projektu ale zabierzesz klauzule static z pliku add.cpp, to też będzie błąd linkera, ponieważ nie będzie wiedział który SF ma użyć w main() ten z add.cpp czy ten z ext.cpp


(Quentin) #5

No i wyjaśnił - dzięki wielkie :wink: