To nie jest blad, dlaczego tak uwazasz? Ale miedzy oboma sposobami jest zasadnicza roznica.
-
sposob: extern
W takim wypadku zmienna x
bedzie miala taka sama wartosc miedzy jednostkami kompilacji (zmienna o zasiegu globalnym). To oznacza, ze jesli zmienisz jej wartosc w jednym pliku CPP, taka sama bedzie jej wartosc w pozostalych plikach CPP. To jedna i ta sama zmienna, wspoldzielona przez caly program.
-
sposob: static
W tym wypadku x
bedzie zmienna o zasiegu pliku. Oznacza to, ze w kazdym pliku CPP bedzie to de facto inna zmienna. Zmienna x
w pliku klasa1.cpp
to zupelnie inna zmienna niz ta w pliku klasa2.cpp
.
Ale przede wszystkim: dlaczego miales blad? Dlatego, ze pliki poprzez #include
sa przed kompilacja pliku CPP wklejane w miejsce dyrektywy. Oznacza to, ze gdy w pliku klasa1.cpp
i klasa2.cpp
dodajesz #include "utils.h"
, zarowno w pliku klasa1.cpp
jak i klasa2.cpp
definiowana jest zmienna globalna x
. I na etapie kompilacji wszystko jest OK, bo kompilacja plikow CPP jest niezalezna od siebie. Problem pojawia sie przy konsolidacji (linkowaniu), bo w dwoch modulach znajduje sie taka sama zmienna i linker nie wie, z ktora ma polaczyc odwolania w programie wynikowym.
Rozwiazaniem jest wiec albo extern
w naglowku, ktory mowi kompilatorowi, ze gdzies w programie bedzie zmienna o takiej nazwie i linker bedzie do niej laczyl - czyli typowa zmienna globalna, ktora moze w calym programie byc zdefiniowana tylko raz. Albo static
, ktory mowi, ze ta zmienna jest globalna tylko dla tej jednostki kompilacji i nie bedzie udostepniana na zewnatrz (linker nie bedzie o niej wiedzial). Nie ma konfliktow, bo kazda jednostka kompilacji ma wlasna, "prywatna zmienna globalna".