r15.pdf
(
244 KB
)
Pobierz
Szablon dla tlumaczy
Rozdział 15.
Specjalne klasy i funkcje
C++ oferuje kilka sposobów na ograniczenie zakresu i oddziaływania zmiennych i wskaźników.
Do tej pory, dowiedzieliśmy się, jak tworzyć zmienne globalne, lokalne zmienne funkcji,
wskaźniki do zmiennych oraz zmienne składowe klas.
Z tego rozdziału dowiesz się:
•
czym są zmienne statyczne i funkcje składowe,
•
jak używać zmiennych statycznych i statycznych funkcji składowych,
•
jak tworzyć i operować wskaźnikami do funkcji i wskaźnikami do funkcji składowych,
•
jak pracować z tablicami wskaźników do funkcji.
Statyczne dane składowe
Prawdopodobnie do tej pory uważałeś dane każdego obiektu za unikalne dla tego obiektu (i nie
współużytkowane pomiędzy obiektami klasy). Gdybyś miał na przykład pięć obiektów klasy
Cat
,
każdy z nich miałby swój wiek, wagę, itp. Wiek jednego kota nie wpływa na wiek innego.
Czasem zdarza się jednak, że chcemy śledzić pulę danych. Na przykład, możemy chcieć wiedzieć,
ile obiektów danej klasy zostało stworzonych w programie, a także ile z nich istnieje nadal.
Statyczne zmienne składowe są współużytkowane przez wszystkie egzemplarze obiektów klasy.
Stanowią one kompromis pomiędzy danymi globalnymi, które są dostępne dla wszystkich części
programu, a danymi składowymi, które zwykle są dostępne tylko dla konkretnego obiektu.
Statyczne składowe można traktować jako należące do całej klasy, a nie tylko do pojedynczego
obiektu. Zwykła dana składowa odnosi się do pojedynczego obiektu, a dana składowa statyczna
odnosi się do całej klasy. Listing 15.1 deklaruje obiekt
Cat
, zawierający statyczną składową
HowManyCats
(ile kotów). Ta zmienna śledzi, ile obiektów klasy
Cat
zostało utworzonych.
Śledzenie odbywa się poprzez inkrementację statycznej zmiennej
HowManyCats
w konstruktorze
klasy i dekrementowanie jej w destruktorze.
Listing 15.1. Statyczne dane składowe
0: //Listing 15.1 Statyczne dane składowe
1:
2: #include <iostream>
3: using namespace std;
4:
5: class Cat
6: {
7: public:
8: Cat(int age):itsAge(age){HowManyCats++; }
9: virtual ~Cat() { HowManyCats--; }
10: virtual int GetAge() { return itsAge; }
11: virtual void SetAge(int age) { itsAge = age; }
12: static int HowManyCats;
13:
14: private:
15: int itsAge;
16:
17: };
18:
19: int Cat::HowManyCats = 0;
20:
21: int main()
22: {
23: const int MaxCats = 5; int i;
24: Cat *CatHouse[MaxCats];
25: for (i = 0; i<MaxCats; i++)
26: CatHouse[i] = new Cat(i);
27:
28: for (i = 0; i<MaxCats; i++)
29: {
30: cout << "Zostalo kotow: ";
31: cout << Cat::HowManyCats;
32: cout << "\n";
33: cout << "Usuwamy kota, ktory ma ";
34: cout << CatHouse[i]->GetAge();
35: cout << " lat\n";
36: delete CatHouse[i];
37: CatHouse[i] = 0;
38: }
39: return 0;
40: }
Wynik
Zostalo kotow: 5
Usuwamy kota, ktory ma 0 lat
Zostalo kotow: 4
Usuwamy kota, ktory ma 1 lat
Zostalo kotow: 3
Usuwamy kota, ktory ma 2 lat
Zostalo kotow: 2
Usuwamy kota, ktory ma 3 lat
Zostalo kotow: 1
Usuwamy kota, ktory ma 4 lat
Analiza
W liniach od 5. do 17. została zadeklarowana uproszczona klasa
Cat
. W linii 12. zmienna
HowManyCats
została zadeklarowana jako statyczna zmienna składowa typu
int
.
Sama deklaracja zmiennej
HowManyCats
nie definiuje wartości całkowitej i nie jest dla niej
rezerwowane miejsce w pamięci. W odróżnieniu od zwykłych zmiennych składowych, w
momencie tworzenia egzemplarzy obiektów klasy
Cat
, nie jest tworzone miejsce dla tej zmiennej
statycznej, gdyż nie znajduje się ona w obiekcie. W związku z tym musieliśmy zdefiniować i
zainicjalizować tę zmienną w linii 19..
Programistom bardzo często zdarza się zapomnieć o zdefiniowaniu statycznych zmiennych
składowych klasy. Nie pozwól, by przydarzało się to tobie! Oczywiście, gdy się przydarzy, linker
zgłosi komunikat błędu, informujący o niezdefiniowanym symbolu, na przykład taki jak poniższy:
undefined symbol Cat::HowManyCats
(niezdefiniowany symbol Cat::HowManyCats)
Nie musimy definiować zmiennej
itsAge
, gdyż nie jest statyczną zmienną składową i w związku
z tym jest definiowana za każdym razem, gdy tworzymy obiekt klasy
Cat
(w tym przypadku w
linii 26. programu).
Konstruktor klasy
Cat
w linii 8. inkrementuje statyczną zmienną składową. Destruktor (zawarty w
linii 9.) dekrementuje ją. Zatem zmienna
HowManyCats
przez cały czas zawiera właściwą ilość
obiektów
Cat
, które zostały utworzone i jeszcze nie zniszczone.
Program sterujący. zawarty w liniach od 21. do 40., tworzy pięć egzemplarzy obiektów klasy
Cat
i umieszcza je w pamięci. Powoduje to pięciokrotne wywołanie konstruktora, w związku z czym
następuje pięciokrotne inkrementowanie zmiennej
HowManyCats
od jej początkowej wartości
0
.
Następnie program w pętli przechodzi przez wszystkie pięć elementów tablicy i przed usunięciem
kolejnego wskaźnika do obiektu
Cat
wypisuje wartość zmiennej
HowManyCats
. Wydruk
pokazuje to, że wartością początkową jest
5
(gdyż zostało skonstruowanych pięć obiektów) i że
przy każdym wykonaniu pętli pozostaje o jeden obiekt
Cat
mniej.
Zwróć uwagę, że zmienna
HowManyCats
jest publiczna i jest używana bezpośrednio w funkcji
main()
. Nie ma powodu do udostępniania zmiennej składowej w ten sposób. Najlepszą metodą
jest uczynienie z niej prywatnej składowej i udostępnienie publicznego akcesora (o ile ma być ona
dostępna wyłącznie poprzez egzemplarze klasy
Cat
). Z drugiej strony, gdybyśmy chcieli
korzystać z tej danej bezpośrednio, niekoniecznie posiadając obiekt klasy
Cat
, mamy do wyboru
dwie opcje: możemy zadeklarować tę zmienną jako publiczną, tak jak pokazano na listingu 15.2,
albo dostarczyć akcesor w postaci statycznej funkcji składowej, co zostanie omówione w dalszej
części rozdziału.
Listing 15.2. Dostęp do statycznych danych składowych bez obiektu
0: //Listing 15.2 Statyczne dane składowe
1:
2: #include <iostream>
3: using namespace std;
4:
5: class Cat
6: {
7: public:
8: Cat(int age):itsAge(age){HowManyCats++; }
9: virtual ~Cat() { HowManyCats--; }
10: virtual int GetAge() { return itsAge; }
11: virtual void SetAge(int age) { itsAge = age; }
12: static int HowManyCats;
13:
14: private:
15: int itsAge;
16:
17: };
18:
19: int Cat::HowManyCats = 0;
20:
21: void TelepathicFunction();
22:
23: int main()
24: {
25: const int MaxCats = 5; int i;
26: Cat *CatHouse[MaxCats];
27: for (i = 0; i<MaxCats; i++)
28: {
29: CatHouse[i] = new Cat(i);
30: TelepathicFunction();
31: }
32:
33: for ( i = 0; i<MaxCats; i++)
34: {
35: delete CatHouse[i];
36: TelepathicFunction();
37: }
38: return 0;
39: }
40:
41: void TelepathicFunction()
42: {
43: cout << "Zostalo jeszcze zywych kotow: ";
44: cout << Cat::HowManyCats << "\n";
45: }
Wynik
Zostalo jeszcze zywych kotow: 1
Zostalo jeszcze zywych kotow: 2
Zostalo jeszcze zywych kotow: 3
Zostalo jeszcze zywych kotow: 4
Zostalo jeszcze zywych kotow: 5
Zostalo jeszcze zywych kotow: 4
Zostalo jeszcze zywych kotow: 3
Zostalo jeszcze zywych kotow: 2
Zostalo jeszcze zywych kotow: 1
Zostalo jeszcze zywych kotow: 0
Analiza
Plik z chomika:
Wojteczek
Inne pliki z tego folderu:
rdodc.pdf
(84 KB)
rdodb.pdf
(72 KB)
rdoda.pdf
(184 KB)
r21.pdf
(370 KB)
r20.pdf
(275 KB)
Inne foldery tego chomika:
Cisco
Kurs C++ od zera do hackera v. 1.0
Pascal
ZAHASŁOWANE
Zgłoś jeśli
naruszono regulamin