Šiame trumpame straipsniūkštyje palyginsime įdomų skirtumuką tarp C ir C++,
kuris parodo, kad šiose giminingose kalbose objektams skirtingai
priskirimos pradinės reikšmės. Pavyzdžiui, klasės turi konstruktorius,
kurie globaliems objektams priskiria pradines reikšmes, kurios nežinomos
kompiliavimo metu.
Kitas skirtumas - C++ nėra prasmės perduoti valdymą toliau, nei
priskiriamos pradinės reikšmės. Pateikiamas pavyzdėlis leistinas
C, bet tik ne C++ kalboje, nes bus atspausdinta šiukšlės, esančios
steke, reikšmė.
#include
Ne visi įsigilina į gana savotiško termino "static" prasmę C++ kalboje.
Aprašuose jis nurodo objekto atminties gyvavimo laikotarpį. Juk
atmintis gali būti trijų tipų: statinė ("static"), dinaminė ("heap")
ir automatinė ("stack"). Įprasta (bet nebūtina), kad programai skiriama
atmintis yra suskirstoma taip:
Na o kitame pavyzdėlyje tokia funkcija yra vidinė klasės funkcija ir
ją naudoti gali tik kiti klasės nariai:
Tačiau, jei jis buvo sukurtas, - prieš baigiant programą jį reikia sunaikinti.
Kas tai padarys? Tai gali padaryti tik pagrindinė programa, o ne funkcija
"F".
+------------------------------+
| Programos kodas | Kaip matote, stekas ir dinaminė
+------------------------------+ atmintis iš skirtingų pusių plečiasi
| Statiniai duomenys | vienas link kito.
+------------------------------+
| Dinaminė sritis (heap) | Steko atmintis naudojama kviečiant
| | | | paprogrames (funkcijas), o "kupetynas"
| V | dinamiškai išskiriant ir naikinant
+------------------------------+ atmintį objektams (operatoriai "new"
| Laikinai nenaudojamas plyšys | ir "delete") -
+------------------------------+
| ^ | Pastovios ("static") atminties kiekis
| | | | nekinta per visą programos gyvavimo
| Stekas | laiką.
+------------------------------+
Užsirašykite ant popieriaus skiautelės ar smegenų raukšlelės, kad
pateiktame pavyzdėlyje kintamojo "Lokalus" atmintis irgi gyvuos,
kol gyvuos ir programa, nors jis naudojamas tik "Funkcija" viduje.
void Funkcija()
{ static int Lokalus = 37;
int Laikinas = 45;
}
O atmintis kintamajam "Laikinas" yra išskiriama iš steko kiekvieno
kreipinio į "Funkcija" metu. Ir kiekvieną kartą iš naujo jam priskiriama
pradinė reikšmė.
Antra "static" paskirtis - nurodyti objekto pasiekiamumo sritį, pvz.,
static int X = 37;
static void F() {}
nurodo, kad kintamąjį "X" ir funkciją "F" galima naudoti tik tame
modulyje (faile), kuriame jie aprašyti. Pasiekiamumas ir gyvavimo laikas
nėra tas pats - palyginkite bent paskutinius du pavyzdėlius.
Taip buvo C kalboje, taip yra ir C++ - kaip danguje, taip ir ant žemės.
Tačiau leidžiama naudoti statinius klasės narius, pvz.,
class Objektas { || Statinius klasės narius gali naudoti
public: static int Bendras; || bet kuris klasės objektas.
static void F(); || Aprašius du objektus:
int T; || Objektas Obj1;
}; || Objektas Obj2;
|| jie abu turės tą patį narį "Bendras",
|| tačiau "T" skirsis.
int Objektas::Bendras = 0; ||
void Objektas::F() {} ||
Taip aprašyti nariai palengvina informacijos apsikeitimą tarp skirtingų
tos pačios klasės objektų. Na o "static" funkcijos yra tarsi klasės
pagalbinės funkcijos. Pavyzdžiui, klasė darbui su kalendoriumi gali
turėti "static" funkciją, kuri nustato, ar jai nurodyti metai yra
keliamieji. Tokios funkcijos veiksmai reikalingi šiai klasei,
tačiau nedirba nė su vienu šios klasės konkrečiu objektu. Žinoma,
ją galima daryti visuotine (globalia), tačiau žymiai vaizdžiau
ją įtraukti į klasę.
class Kalendorius {
static int ArKeliamieji(int Metai); // arba static BOOL ...
public: // kitkas
}
Įdomus aspektas, kai paliečiami klasės konstruktoriai, pavyzdžiui,
class Objektas {
public: Objektas();
~Objektas();
};
void F() { static Objektas obj; }
Mūsų aprašytas objektas turi konstruktorių, kuris yra iškviečiamas
aprašant objektą. Tačiau negalima kiekvieną kartą kviečiant "F", kviesti
ir konstruktorių. Juk objektas statinis ir gyvuos, kol gyvuos pati programa.
Todėl konstruktorius turėtų būti kviečiamas tik pirmą kartą kviečiant
funkciją. Jei ji nebus niekada iškviesta - objektas neegzistuos!