Obiekty i klasy
Obiekt: abstrakcyjny byt reprezentujący lub opisujący pewną rzecz lub pojęcie obserwowane w świecie rzeczywistym
Obiekt charakteryzuje się pewnym zakresem zachowań.
Obiekt przechowuje pewne informacje na swój temat (atrybuty).
Klasa: uogólnienie podobnych do siebie obiektów.
Obiekt jest to egzemplarz danej klasy.
Tworząc klasę określamy cechy i możliwości wszystkich przyszłych obiektów tej klasy.
Komunikat: sygnał skierowany do obiektu wywołujący określoną metodę (operację), którą należy wykonać na obiekcie.
Klienci klasy: obiekty, klasy, aplikacje, które wysyłają zlecenia na wykonanie pewnych usług. Klient musi wiedzieć co dana klasa robi, a nie jak ona to robi.
Przełożone na język programowania:
Klasa: typ definiowany przez użytkownika
Obiekt: zmienna tego typu, czyli egzemplarz klasy
Wysłanie komunikatu: wywołanie funkcji (metody) związanej z obiektem
Klasa zawiera składowe:
pola danych: zmienne, które służą do przechowania wartości atrybutów obiektu
metody (funkcje składowe): funkcje, które określają zachowanie obiektu
poziomy dostępu do składowych: od tego, na którym poziomie znajduje się składowa zależy możliwość dostępu do niej z innych miejsc programu
Metody są takie same dla wszystkich obiektów danej klasy.
Dane przechowywane w obiektach są różne.
Składowe prywatne tworzą implementację klasy.
Składowe publiczne tworzą publiczny interfejs klasy.
Przykład 1:
// DEFINICJA KLASY
class TV {
int program;
bool wlaczony;
public:
// INTERFEJS KLASY
// konstruktor domyślny - przypisanie wartości początkowych składowym prywatnym
TV() {program=2; wlaczony=false;}
// metody klasy
void zmienProgram(int p) // zmiana składowej prywatnej
{ if (wlaczony) program=p; }
void wlacz(void) // zmiana składowej prywatnej
{ wlaczony=true; }
void wylacz(void) // zmiana składowej prywatnej
{ wlaczony=false; }
};
//
// KLIENT KLASY
int main ()
{
TV kuchniaTV;
kuchniaTV.zmienProgram(4);
kuchniaTV.wlacz();
kuchniaTV.zmienProgram(4);
}
Elementy składowe klasy:
Pola danych: program, wlaczony
Metody: zmienProgram(), wlacz(), wylacz()
Konstruktor inicjujący: TV()
Poziomy dostępu do składowych:
public - dostępne z zewnątrz klasy
private - dostępne tylko przez metody klasy
Zasada:
domyślnym trybem dostępu do składowych klasy jest private
zatem dopóki w obrębie definicji klasy nie wystąpi w sposób jawny kwalifikator public, wszystkie dane i metody są automatycznie zakwalifikowane jako prywatne.
Metody to funkcje należące do klasy.
Wszystkie metody mają dostęp do pól danych (zmiennych) klasy.
Funkcje zewnętrzne to funkcje nie należące do klasy.
Funkcje zewnętrzne mają dostęp tylko do składowych publicznych.
Dwa style definiowania klas:
składowe prywatne na początku klasy
składowe publiczne na początku klasy - wyróżniany jest w ten sposób interfejs klasy
Przykład 2: Zdefiniować klasę Figura, która będzie obliczać powierzchnię figur.
Uproszczony schemat postępowania:
Nadać nazwę klasie.
Dodać do klasy pola danych.
Dodać do klasy metody (prototypy funkcji), które będą manipulowały wewnętrznymi danymi klasy.
Dodać do klasy konstruktor.
Zdefiniować kody metod i konstruktora.
Utworzyć moduł główny, w który tworzone będą obiekty danej klasy i opisane będzie ich działanie.
ad. 1 Nadanie nazwy klasie
#include <iostream.h>
class Figura
{
// klasa jest na razie pusta
};
int main()
{
return 0;
}
ad. 2 Dodanie do klasy pól danych
#include <iostream.h>
class Figura
{
// pola danych są prywatne
private:
int dlugosc;
int szerokosc;
int powierzchnia;
};
int main()
{
return 0;
}
ad 3 Dodanie do klasy metod
class Figura
{
// pola danych są prywatne
private:
int dlugosc;
int szerokosc;
int powierzchnia;
// metody są publiczne
public:
void ObliczPow(void);
void DrukujPow(void);
};
int main()
{
return 0;
}
ad 4. Dodanie do klasy konstruktora
class Figura
{
// pola danych są prywatne
private:
int dlugosc;
int szerokosc;
int powierzchnia;
// metody są publiczne
public:
Figura(int d=0, int s=0); //konstruktor jest publiczny
void ObliczPow(void);
void DrukujPow(void);
};
int main()
{
return 0;
}
ad 5. Zdefiniowanie metod i konstruktora
#include <iostream.h>
class Figura
{
private:
int dlugosc;
int szerokosc;
int powierzchnia;
public:
Figura(int d=0, int s=0);
void ObliczPow(void);
void DrukujPow(void);
};
void Figura::ObliczPow(void)
{
powierzchnia=dlugosc*szerokosc;
}
void Figura::DrukujPow(void)
{
cout << "Powierzchnia wynosi : "<<powierzchnia;
}
Figura::Figura(int d, int s)
{
dlugosc=d;
szerokosc=s;
}
main()
{
return 0;
}
ad 6 . Funkcja główna - utworzenie obiektów i
#include <iostream.h>
class Figura
{
private:
int dlugosc;
int szerokosc;
int powierzchnia;
public:
prostokat(int d=0, int s=0);
void ObliczPow(void);
void DrukujPow(void);
};
void Figura::ObliczPow(void)
{
powierzchnia=dlugosc*szerokosc;
}
void Figura::DrukujPow(void)
{
cout << "Powierzchnia wynosi : "<<powierzchnia<<endl;
}
Figura::Figura(int d, int s)
{
dlugosc=d;
szerokosc=s;
}
main()
{
int x,y;
cout << "Podaj dlugosc: ";
cin >> x;
cout << "Podaj szerokosc: ";
cin >> y;
Figura a(x,y); // utwórz prostokąt a
a.ObliczPow(); // oblicz powierzchnię prostokąta a
a.DrukujPow(); // drukuj powierzchnię prostokąta a
return 0;
}
Przykład 3. Klasa do obliczeń na ułamkach Ulamek
#include <iostream.h>
#include <math.h>
class Ulamek
{ int l; // licznik
int m; // mianownik
int nwp(int p, int q); // największy wspólny podzielnik
public:
Ulamek(int a=0, int b=1) // Konstruktor
{ int q=nwp(a,b);
if(b < 0) q = -q; // mianownik ma być zawsze dodatni
l = a/q;
m = b/q;
}
int ZwrocLicznik()const { return l; }
int ZwrocMian()const { return m;}
};
int Ulamek::nwp(int p, int q)
{ int r;
p = abs(p); // obliczenia na wartościach nieujemnych
q = abs(q);
// Przypadki szczególne
if(p == 0) if(q == 0) return 1; else return q;
else if(q == 0) return p;
// p>0, q>0
r = p % q;
while(r) { p = q; q = r; r = p % q; }
return q;
}
int main ()
{
Ulamek f0, f1(1), f2(6,3), f3(f2);
cout << "TEST KLASY Ulamek\n";
cout << f0.ZwrocLicznik() << '/' << f0.ZwrocMian() << endl;
cout << f1.ZwrocLicznik() << '/' << f1.ZwrocMian() << endl;
cout << f2.ZwrocLicznik() << '/' << f2.ZwrocMian() << endl;
cout << f3.ZwrocLicznik() << '/' << f3.ZwrocMian() << endl;
return 0;
}
Przykład 4. Klasa Stos do obsługi stosu, stos jest implementowany za pomocą tablicy tworzonej dynamicznie.
class Stos {
private:
int* s; // wierzchołek stosu
int n; // liczba elementów stosu
public:
void Odloz(int element);
int Zdejmij(void);
bool jestPusty() const;
// konstruktor
Stos(int maxEl);
};
Stos::Stos(int maxE)
{
s = new int[maxE]; // przydziel potrzebną pamięć
if (s==0) // sprawdź, czy została przydzielona pamięć
exit(1);
n=0;
}
bool Stos::jestPusty() const
{
return n==0;
}
void Stos::Odloz(int element)
{
s[n++]=element;
}
int Stos::Zdejmij(void)
{
return s[--n];
}
Przykład 5. Zastosowanie stosu - obliczanie wartości wyrażenia postfiksowego (Sedgewick, Algorytmy w C++, str. 132)
Odczytujemy kolejne znaki od lewej do prawej.
Jeżeli napotkana zostanie liczba, jest umieszczana na stosie.
Jeśli napotkany zostanie operator, pobiera się dwie liczby ze stosu, wykonuje operację wskazaną operatorem i wynik umieszcza na stosie.
#include <iostream.h>
#include <string.h>
#include <ctype.h>
int main (int argc, char *argv[])
{
char *a=argv[1];
int n=strlen(a);
Stos A(n);
cout << argv[1]<<endl;
for (int i=0; i<n; i++)
{
if (a[i]=='+')
A.Odloz(A.Zdejmij() + A.Zdejmij());
if (a[i]=='*')
A.Odloz(A.Zdejmij() * A.Zdejmij());
if (isdigit(a[i]))
A.Odloz(0);
while (isdigit(a[i]))
A.Odloz(10*A.Zdejmij() + (a[i++]-'0'));
}
cout << A.Zdejmij() << endl;
return(0);
}
Zliczanie obiektów
czyli
statyczne pola danych i statyczne funkcje
Zwykłe pola danych zawierają wartości charakterystyczne dla danego obiektu, są niedostępne w innym obiekcie i są tworzone jedno na obiekt.
Statyczne pole danych klasy to takie pole danych, które istnieje tylko w jednym egzemplarzu, niezależnie od liczby utworzonych obiektów tej klasy, jest tworzone jedno na klasę.
Metoda, która korzysta tylko ze składowych statycznych może być zadeklarowana jako funkcja statyczna. Może być ona wywoływana na rzecz obiektu lub jako samodzielna.
Przykład 6. Zliczanie tworzonych punktów
#include <iostream.h>
class Punkt
{ int x, y;
static int licznik; // Zmienna statyczna: licznik punktów
public:
Punkt (int, int);
~Punkt();
void Wyswietl();
// Funkcja statyczna: zwraca wartość typu int, liczbę punktów
static int LiczbaPkt();
};
// Przypisanie wartości początkowej zmiennej statycznej
int Punkt::licznik=0;
Punkt::Punkt(int xx, int yy) // Konstruktor
{ x=xx;y=yy;
licznik++; // Aktualizacja licznika gdy tworzony jest nowy
// punkt czyli wywoływany konstruktor
}
Punkt::~Punkt() // Destruktor
{ licznik--; } // Aktualizacja licznika gdy usuwany jest
// punkt czyli wywoływany destruktor
void Punkt::Wyswietl()
{ cout<<" Wspolrzedne punkt " << x << " " << y << "\n"; }
int Punkt::LiczbaPkt()
{ return licznik; }
int main() {
cout << "Poczatkowa ilosc punktow: "
Punkt::LiczbaPkt() << endl;;
Punkt a(0,0), b(1,1);
cout << "Liczba punktow po inicjacji obiektow: "
<<Punkt::LiczbaPkt()<<endl;;
a.Wyswietl();
b.Wyswietl();
}
Klasy zagnieżdżone
Przykład 7. Zdefiniować klasę Stos (przykład 4) do obsługi stosu. Stos zrealizować za pomocą listy z dowiązaniami.
class Stos
{
private:
struct wezel
{ int el;
wezel *nast;
wezel (int x, wezel *t;
{ el=x; nast=t;}
};
typedef wezel *lacze;
lacze glowa;
public:
void Wstaw(int x)
{ glowa = new wezel(x,glowa);}
int Zdejmij(void)
{ int v=glowa->el;
lacze t=glowa->nast;
delete glowa;
glowa = t;
return v;
}
bool Pusty() const { return glowa==0; }
Stos(int) { glowa = 0;}
};
Szczegóły techniczne
Klasa
Definicja klasy określa budowę i sposób przetwarzania obiektów klasy.
Definicja klasy ma postać:
class nazwa_klasy
{
private: // pola danych i funkcje prywatne
typ nazwa_zmiennej;
...
public: // pola danych i funkcje publiczne
typ nazwa_funkcji();
...
protected: // pola danych i funkcje chronione
...
};
Funkcje składowe klasy nazywane są metodami.
Składowe (dane i metody) zadeklarowane w sekcji public są dostępne w całym programie.
Składowe (dane i metody) zadeklarowane w sekcji private są dostępne jedynie w funkcjach składowych klasy i w funkcjach zaprzyjaźnionych.
Składowe (dane i metody) zadeklarowane w sekcji protected są dostępne jedynie w funkcjach składowych klasy i w funkcjach składowych jej klas pochodnych (dziedziczących).
Jeśli pierwszą grupą składowych są składowe prywatne, to można przed nimi pominąć kwalifikator private. Obowiązuje zasada, że dopóki o obrębie definicji klasy nie wystąpi w sposób jawny kwalifikator public, wszystkie dane i metody są automatycznie zakwalifikowane jako prywatne.
Klasę można definiować za pomocą konstrukcji class lub struct. Struktura jest klasą, w której wszystkie składowe są publiczne. Czyli zapis
struct S { ...};
jest po prostu skrótem zapisu
class S { public: ... };
Przykład:
class Punkt
{
private:
float x; // współrzędna x punktu
float y; // współrzędna y punktu
public:
Punkt (float, float); // konstruktor
void Drukuj(); // wyświetlanie współrzędnych
};
Składowe klasy
Pola danych:
W ciele klasy można używać deklaracji dowolnych danych i struktur danych istniejących w języku C.
Nie wolno inicjalizować składowych.
Metody:
można definiować bezpośrednio w ciele klasy; każda metoda zdefiniowana wewnątrz klasy jest uważana za funkcję wewnętrzną, bez względu na to, czy zostanie poprzedzona słowem kluczowym inline.
można umieszczać w ciele klasy prototyp funkcji składowej (deklarację), zaś definicję funkcji umieszczać na zewnątrz; należy ją wtedy poprzedzić identyfikatorem klasy wraz z operatorem zasięgu.
class MojaKlasa
{
private: // pola danych i funkcje prywatne
...
public: // pola danych i funkcje publiczne
// ta funkcja jest definiowana w ciele klasy
void Fun1(int a)
{
// instrukcje funkcji
}
// ta funkcja jest tylko deklarowana w ciele klasy,
// jest to zapowiedź funkcji, której definicja
// znajduje się na zewnątrz klasy
void Fun2(int, int);
...
};
// Definicja funkcji Fun2
void MojaKlasa::Fun2(int a, int b)
{
// instrukcje funkcji
}
Metody (funkcje składowe) można podzielić na następujące kategorie:
funkcje zarządzające - stosowane automatycznie w momencie tworzenia obiektu klasy (konstruktory) i w momencie jego usuwania (destruktory); należą do składowych publicznych;
funkcje dostępu - ich zadaniem jest udostępnienie składowych prywatnych klasy); należą do składowych publicznych;
funkcje przetwarzające - dokonują operacji na składowych klasy, mogą korzystać z funkcji pomocniczych; ); należą do składowych publicznych;
funkcje pomocnicze wykorzystywane przez inne kategorie funkcji; zazwyczaj są to składowe prywatne.
Obiekty
Obiekt to pojedyncze, indywidualne wystąpienie klasy.
Obiekty definiuje się podobnie do zmiennych, umieszczając listę identyfikatorów za nazwą klasy.
// definicja zmiennej
int x; // definicja zmiennej x
class Punkt {
// tutaj definicja składowych klasy Punkt
...
};
// definicja obiektów
Punkt a; // definicja punktu a
// czyli obiektu a klasy Punkt
Punkt b,c; // definicja punktów b i c (dwóch obiektów)
Proces tworzenia obiektu polega na przydzieleniu mu obszaru pamięci wystarczającego dla składowych będących danymi i strukturami danych, po czym wywoływana jest funkcja składowa będąca konstruktorem obiektu.
Odwołania do składowych obiektu uzyskuje się za pomocą operatora "." umieszczonego po nazwie obiektu.
Przykład:
Punkt a; // deklaracja obiektu a
a.Drukuj(); // wywołanie metody Drukuj na rzecz obiektu a
Funkcje składowe (metody) muszą być wywoływane RAZEM z obiektem.
Konstruktory
Konstruktor jest to specjalna metoda używana do utworzenia obiektu danej klasy.
Są dwa typy konstruktorów:
konstruktor inicjujący,
konstruktor kopiujący.
Konstruktor inicjujący jest automatycznie wywoływany podczas powoływania do życia obiektu (czyli podczas wykonywania instrukcji deklarującej obiekt).
Celem konstruktora inicjującego jest przyporządkowanie pamięci dla nowego obiektu i zainicjowanie pól danych.
Jeśli nie zdefiniuje się żadnego własnego konstruktora inicjującego, to kompilator automatycznie stworzy własny domyślny konstruktor inicjujący. Konstruktor taki nie inicjuje pól danych.
Konstruktor kopiujący jest automatycznie wywoływany podczas kopiowania obiektu. Ma to miejsce jeśli:
definiujemy nowy obiekt za pomocą obiektu istniejącego
Punkt a(1,1), b(a); // definicja obiektu b za pomocą a
przekazujemy obiekt do funkcji
funkcja(a); // przekazanie obiektu a do funkcji
zwracamy obiekt z funkcji
c=funkcja(); // zwrócenie obiektu z funkcji
Celem konstruktora kopiującego jest wykonanie w pamięci kopii obiektu.
Jeśli nie zdefiniuje się żadnego własnego konstruktora kopiującego, to kompilator automatycznie stworzy własny domyślny konstruktor kopiujący.
Konstruktor inicjujący
Jeśli używamy samego określenia konstruktor, zazwyczaj mamy na myśli konstruktor inicjujący.
Konstruktor inicjujący ma taką samą nazwę jak klasa, jest funkcją bez określonego typu wyniku.
Klasa może posiadać wiele konstruktorów inicjujących. O wyborze konstruktora decyduje postać definicji obiektu.
class MojaKlasa
{
public:
MojaKlasa(); // konstruktor bez parametrów
// nazywany jest domyślnym
MojaKlasa(int n); // konstruktor może mieć parametry
...
};
int main()
{
MojaKlasa a; // deklaracja obiektu:
// wywołany zostanie konstruktor domyślny
MojaKlasa b(2); // deklaracja obiektu:
// wywołany zostanie konstruktor z jednym
// parametrem
}
Jeśli nie zdefiniuje się żadnego własnego konstruktora, to kompilator automatycznie stworzy własny konstruktor domyślny czyli bez parametrów. Konstruktor domyślny generowany przez kompilator nie przypisuje wartości początkowych danym klasy.
Zdefiniowanie choć jednego własnego konstruktora spowoduje, że kompilator przyjmie, że klasa ma własne konstruktory i nie utworzy swojego konstruktora domyślnego. jeśli potrzebny jest konstruktor bez parametrów, trzeba go samemu utworzyć.
Konstruktor może posiadać parametry domyślne. Dzięki temu ogranicza się liczbę niezbędnych konstruktorów.
class MojaKlasa
{
public:
MojaKlasa(int n=0);
...
};
int main()
{
MojaKlasa a; // wywołany zostanie konstruktor z n=0
MojaKlasa b(2); // wywołany zostanie konstruktor z n=2
}
Tworzenie obiektów z przypisanymi wartościami początkowymi
Konstruktor może przypisywać wartości składowym na dwa sposoby:
pobierać wartości z argumentów i przypisywać je składowym w ciele funkcji:
class X
{
int a,b;
public:
X(int i, int j) {a=i; b=j};
};
korzystać z listy inicjalizującej umieszczonej przed ciałem funkcji, w której definiowane jest powiązanie składowych i argumentów zgodnie ze składnią identyfikator_składowej(identyfikator_argumentu_formalnego):
class X
{
int a,b;
public:
X(int i, int j): a(i), b(j) {}
};
Są dwie metody przesyłania argumentów do konstruktora podczas inicjalizacji obiektu:
posługując się znakiem przypisania =
nazwa_klasy nazwa_obiektu = nazwa_klasy(wartości zmiennych)
Jeśli występuje tylko jeden argument, zapis ten można uprościć:
nazwa_klasy nazwa_obiektu = wartość_zmiennej
za pomocą listy
nazwa_klasy nazwa_obiektu(wartości zmiennych)
Przykład:
class X
{
int i;
public:
X(); // konstruktor domyślny - bez parametrów
X(int x); // konstruktor z jednym parametrem
X(int x, int y) // konstruktor z dwoma parametrami
};
int main()
{
X a; // wywołany konstruktor domyślny
X b(1); // użyty konstruktor X::X(int)
X c=1; // użyty konstruktor X::X(int)
X d(1,1); // użyty konstruktor X::X(int, int)
X d=X(1,1); // użyty konstruktor X::X(int, int)
}
Destruktor
Destruktor jest to specjalna metoda automatycznie wywoływana podczas usuwania obiektu danej klasy, co ma miejsce, gdy:
kończy się zakres deklaracji obiektu,
do wskaźnika obiektu zastosowano operator delete
Celem destruktora jest zakończenie istnienia obiektu danej klasy w sposób przewidywalny i uporządkowany. Jeśli nie zdefiniuje się własnego destruktora, to kompilator automatycznie stworzy własny domyślny destruktor.
Destruktor ma taką samą nazwę jak klasa poprzedzoną znakiem tylda (~), jest funkcją bez określonego typu wyniku.
Można zdefiniować tylko jeden destruktor.
class MojaKlasa
{
public:
MojaKlasa(int n=0); // konstruktor
~MojaKlasa(); // destruktor
...
};
Destruktor jest wywoływany, gdy obiekt jest niszczony (czyli w momencie opuszczania bloku lub programu, w którym występuje instrukcja deklarująca obiekt).
Jeśli nie stworzy się własnego destruktora, to kompilator stworzy destruktor domyślny.
Konstruktor kopiujący
Pierwszym parametrem konstruktora kopiującego jest referencja do obiektu tej samej klasy:
Punkt(Punkt &);
Punkt(const Punkt &);
Przykład:
class X
{
int i;
public:
X(); // konstruktor inicjujący
X(int x, int y) // konstruktor inicjujący
X(const X&); // konstruktor kopiujący
};
int main()
{
X a; // użyty konstruktor inicjujący
X d(1,1); // użyty konstruktor inicjujący
X d=X(1,1); // użyty konstruktor inicjujący
X e(a); // użyty konstruktor kopiujący X::X(const X&)
X d=a; // użyty konstruktor kopiujący X::X(const X&)
}
Przypadki automatycznego używania konstruktora kopiującego:
jeden obiekt jest inicjalizowany za pomocą drugiego
do funkcji jest przekazywany obiekt
funkcja zwraca obiekt
Metody jako funkcje wewnętrzne
Metody klasy można definiować wewnątrz i na zewnątrz definicji klasy.
Każda metoda zdefiniowana wewnątrz klasy jest uważana za funkcję wewnętrzną, bez względu na to, czy zostanie poprzedzona słowem kluczowym inline.
Metoda definiowana na zewnątrz klasy, jeśli ma być funkcją wewnętrzną musi być poprzedzona słowem kluczowym inline .
Metody typu const
Metoda zadeklarowana jako const, nie może zmieniać wartości żadnego pola danych klasy.
Składnia:
void jakasFunkcja() const;
Przykład:
// Funkcja przypisuje punktowi współrzędne podane
// jako parametry wywołania:
// jej zadaniem jest zmiana składowych klasy,
// zatem nie może być zadeklarowana jako const
void UstawPunkt(int x, int x);
//
// Funkcja drukuje współrzędne punktu, na rzecz którego
// została wywołana:
// czyta składowe, ale ich nie zmienia,
// może zatem być zadeklarowana jako const
void DrukujPunkt(void) const;
Zasada: Korzystaj z const wszędzie tam, gdzie jest to możliwe. Pomożesz kompilatorowi wyszukiwać błędy związane z niezamierzonymi zmianami obiektu.
Statyczne pola danych i statyczne funkcje
Statyczne pole danych klasy to taka składowa, która istnieje tylko w jednym egzemplarzu niezależnie od liczby utworzonych obiektów tej klasy.
Deklarację statycznego pola danych w klasie poprzedza się słowem kluczowym static.
Inicjalizacja statycznego pola danych jest umieszczana poza klasą.
class MojaKlasa
{
static int licznik; // deklaracja zmiennej
// ze słowem static
...
public:
MojaKlasa(int n=0);
...
};
int MojaKlasa::licznik=1; // inicjalizacja zmiennej
// bez słowa static
Metoda, która korzysta tylko ze składowych statycznych może być zadeklarowana jako funkcja statyczna.
Metoda statyczna może być wywoływana na rzecz obiektu lub jako samodzielna, poprzedzona wtedy musi być nazwą klasy i operatorem zasięgu :: .
class MojaKlasa
{
static int licznik; // deklaracja zmiennej
// ze słowem static
...
public:
...
static int IleObiektow(); // deklaracja funkcji
// statycznej
...
};
int MojaKlasa::licznik=1; // inicjalizacja zmiennej
// bez słowa static
int IleObiektow() // definicja funkcji statycznej
{
return licznik;
}
1
21
Wykład 2.
domyślnie są to składowe prywatne