Transcript ppt
C++
wykład 3 (22.02.2012)
Składowe statyczne
Funkcje wbudowane
Argumenty domyślne
Funkcje zaprzyjaźnione
Pola statyczne
Każdy obiekt danej klasy ma swój własny
zestaw pól z danymi.
Pole statyczne, z deklaratorem static, nie
jest częścią obiektu, istnieje poza
jakimkolwiek obiektem i jest wspólne dla
wszystkich obiektów danej klasy.
Pole statyczne istnieje przez cały czas życia
programu, nawet wtedy gdy nie utworzono
żadnego obiektu danej klasy.
Pola statyczne
Deklaracja pola statycznego w ciele klasy (w pliku
nagłówkowym) nie jest jego definicją.
Przykład klasy z deklaracją pola statycznego:
class data
{
int dz, mies, rok;
public:
data (int d, int m, int r)
: dz(d), mies(m), rok(r) {/*…*/}
static data poczatek_kalendarza;
};
Definicję pola statycznego należy umieścić poza klasą (w pliku
źródłowym).
Przykład definicji pola statycznego poza klasą:
data data::poczatek_kalendarza(15,10,1582);
Pola statyczne
Odniesienie się do pola statycznego poprzez
nazwę klasy:
klasa::pole_stat
Do pola statycznego można się też odnieść
poprzez jakikolwiek obiekt danej klasy:
klasa ob, *wsk;
// …
ob.pole_stat
wsk->pole_stat
Statyczne funkcje składowe
Statyczna funkcja składowa, z deklaratorem
static, nie odnosi się do żadnego obiektu
danej klasy.
Statyczna funkcja składowa może być
wywołana w dowolnym momencie, nawet
wtedy gdy nie utworzono żadnego obiektu
danej klasy.
Deklaracja statycznej funkcji składowej
znajduje się w ciele klasy (w pliku
nagłówkowym) a jej definicja jest poza klasą
(w pliku źródłowym).
Statyczne funkcje składowe
Przykład klasy z deklaracją statycznej funkcji składowej:
class data
{
int dz, mies, rok;
public:
data (int d, int m, int r)
: dz(d), mies(m), rok(r) {/*…*/}
static int roznica (data p, data k);
};
Przykład definicji statycznej funkcji składowej:
int data::roznica (data p, data k) {/*…*/}
W ciele statycznej funkcji składowej nie wolno odnosić się do
składowych instancyjnych ani do wskaźnika this.
Do statycznej funkcji składowej można odnieść się poprzez
nazwę klasy albo poprzez jakikolwiek obiekt danej klasy.
Funkcje wbudowane
Funkcje wbudowane, oznaczone deklaratorem
inline, są rozwijane w miejscu wywołania.
Ich definicja musi być znana w momencie kompilacji
a nie linkowania, dlatego nie tylko ich deklaracja ale
również definicja znajduje się w pliku nagłówkowym.
Deklarator inline to tylko sugestia dla kompilatora
aby wbudowywał funkcję w miejscu jej wywołania.
Funkcja inline zostanie skompilowane jako outline w
przypadku, gdy:
kompilujemy program do pracy z debuggerem,
funkcja jest rekurencyjna,
pobieramy w programie adres funkcji.
Funkcje wbudowane
Wbudowywanie funkcji w kod ma sens w przypadku
krótkich funkcji.
Funkcje wbudowane zwiększają rozmiar programu
wynikowego ale przyspieszają jego działanie.
Przykład funkcji wpudowanej:
inline int zaokraglenie (double d)
{
return d<0 ? int(d-.5) : int(d+.5);
}
Wbudowane funkcje składowe
W klasie też można definiować wbudowane
funkcje składowe.
Metoda zdefiniowana w klasie jest
traktowana jako inline.
Metody inline można także definiować poza
klasą.
Wbudowane funkcje składowe
Przykład klasy z metodami wbudowanymi:
class data
{
int dz, mies, r;
public:
data (int d, int m, int r);
int dzien (void) const;
int miesiac (void) const { return mies; }
inline int rok (void) const { return r; }
};
inline data::data (int d, int m, int r)
: dz(d), mies(m), r(r) {}
inline int data::dzien (void) const
{ return dz; }
Argumenty domyślne
Często mamy taką sytuację, że w ogólnym
przypadku funkcja wymaga podania większej
liczby argumentów niż w przypadku
najprostszym, albo że wartości niektórych
argumentów często się powtarzają.
Argumenty funkcji globalnych i funkcji
składowych w klasie mogą posiadać
argumenty domyślne.
Argumenty domyślne są formą przeciążania
nazwy funkcji.
Argumenty domyślne
Argumenty domyślne mogą występować tylko
na końcu listy argumentów.
Wartości domyślne nadawane argumentom
domyślnym podaje się tylko w deklaracji
funkcji, w definicji się tego nie powtarza.
Przy wywoływaniu funkcji z argumentami
domyślnymi można pomijać argumenty
domyślne od końca.
Wszystkie argumenty mogą być domyślne.
Argumenty domyślne
Przykład funkcji z argumentem domyślnym:
// deklaracja
void drukuj (int x, int podst=10);
// definicja
void drukuj (int x, int podst) {/*…*/}
// wywołania
drukuj(63); // wynik 63
drukuj(63,16); // wynik 3F
drukuj(63,2); // wynik 111111
Nienazwane argumenty
Jeśli argumentu nazwanego nie używa się w ciele
funkcji lub funkcji składowej, to kompilator będzie
generował ostrzeżenia.
Argumenty, których nie używa się w ciele funkcji
mogą nie posiadać swojej nazwy.
Również argumenty domyślne mogą nie posiadać
nazwy.
Przykład funkcji z nienazwanym argumentem:
void buczenie (int) { /*…*/ }
Funkcja bez argumentów
Jeśli funkcja nie ma żadnych argumentów, to
powinno się ją zadeklarować z argumentem void.
Przykład:
void buczenie (void);
// to jest równoważne z
// void buczenie ();
// w języku C byłoby to równoważne z
// void buczenie (...);
Funkcje zaprzyjaźnione
Problem z kwiatkami w domu w czasie
dalekiej podróży służbowej.
Funkcja, która jest przyjacielem klasy, ma
dostęp do wszystkich jej prywatnych i
chronionych składowych.
To klasa deklaruje, które funkcje są jej
przyjaciółmi.
Deklaracja przyjaźni może się pojawić w
dowolnej sekcji i jest poprzedzona słowem
kluczowym friend.
Funkcje zaprzyjaźnione
Przykład klasy z funkcją zaprzyjaźnioną:
// klasa z funkcją zaprzyjaźnioną
class pionek
{
int x, y;
// …
friend void raport (const pionek &p);
};
// funkcja, która jest przyjacielem klasy
void raport (const pionek &p)
{
cout << "(" << p.x << ", " << p.y << ")";
}
Funkcje zaprzyjaźnione
Nie ma znaczenia, w której sekcji (prywatnej,
chronionej czy publicznej) pojawi się deklaracja
przyjaźni.
Funkcja zaprzyjaźniona z klasą nie jest jej składową,
nie może używać wskaźnika this w stosunku do
obiektów tej klasy.
Jedna funkcja może się przyjaźnić z kilkoma
klasami.
Istotą przyjaźni jest dostęp do niepublicznych
składowych w klasie – sensowne jest deklarowanie
przyjaźni, gdy dana funkcja pracuje z obiektami tej
klasy.
Funkcje zaprzyjaźnione
Można także umieścić w klasie nie tylko
deklarację funkcji zaprzyjaźnionej, ale
również jej definicję; tak zdefiniowana
funkcja:
jest nadal tylko przyjacielem klasy;
jest inline;
może korzystać z typów zdefiniowanych w klasie.
Funkcją zaprzyjaźnioną może być funkcja
składowa z innej klasy.
Klasy zaprzyjaźnione
Możemy w klasie zadeklarować przyjaźń z inną
klasą, co oznacza, że każda metoda tej innej klasy
jest zaprzyjaźniona z klasą pierwotną.
Przykład:
class A
{
friend class B;
// …
};
Przyjaźń jest jednostronna.
Przyjaźń nie jest przechodnia.
Przyjaźni się nie dziedziczy.
Klasy zaprzyjaźnione
Dwie klasy mogą się przyjaźnić z wzajemnością:
class A;
class B
{
friend class A;
// …
};
class A
{
friend class B;
// …
};