Zaawansowane funkcje 189
Dotychczas, wartości wewnętrznych zmiennych klasy były ustalane wewnątrz treści konstruktorów. Jednakże, każdy konstruktor powinien składać się z dwóch części, inicjalizującej i treści.
Większość zmiennych można zainicjować w dowolnej z tych części, albo poprzez inic-jalizację w części inicjalizującej, albo przez przypisanie wartości w treści konstruktora. Jednak bardziej elegancko i bardziej efektywnie jest wykorzystać do tego część inicjalizującą. Oto przykład prawidłowej inicjalizacji zmiennych wewnętrznych:
KOT(): // nazwa konstruktora i parametry
jegoWiek(5), // lista inicjalizacji
jegoWaga(8)
{ ) // treść konstruktora
Po nawiasie zamykającym listę parametrów konstruktora postaw dwukropek.
Następnie wpisz nazwę zmiennej i w nawiasach podaj wyrażenie, którego wartość ma być nadana tej zmiennej. Inicjalizację zmiennych oddzielaj przecinkami. Pamiętaj, że referencje i stałe muszą być inicjalizowane, nie można im przypisywać wartości. W celu nadania im wartości trzeba wykorzystać metodę podaną powyżej. Powiedzieliśmy sobie, że inicjalizacja zmiennych wewnętrznych jest bardziej efektywna niż przypisywanie im wartości. Żeby to wytłumaczyć musimy najpierw dokładniej poznać zasady działania konstruktora kopiującego.
Podobnie jak w przypadku zwykłego konstruktora i destruktora, kompilator dostarcza również kopiujący konstruktor domyślny. Konstruktor kopiujący jest wywoływany w momencie tworzenia kopii obiektu danej klasy.
Kiedy obiekt jest przekazywany przez wartość, jako parametr lub ewentualnie wartość zwracana, to jest wykonywana chwilowa, robocza kopia tego obiektu. Jeśli jest to obiekt klasy zdefiniowanej przez użytkownika, to jest wywoływany konstruktor kopiujący tej klasy.
Konstruktor kopiujący ma tylko jeden parametr: referencje do obiektu tej samej klasy. Dobrze jest deklarować ten parametr jako const, gdyż konstruktor kopiujący nie ma prawa zmieniać zwartości obiektu. Oto przykład deklaracji konstruktora kopiującego:
KOT(const KOT Skotek);
Konstruktor kopiujący z klasy KOT pobiera stałą referencję do istniejącego obiektu klasy KOT. Zadaniem tego konstruktora jest wykonanie w pamięci kopii obiektu kotek.
Domyślny (dostarczany przez kompilator) konstruktor kopiujący, wykonuje kopię każdej zmiennej wewnętrznej obiektu źródłowego i umieszcza w nowym obiekcie. Jest to bardzo „płytkie” kopiowanie i o ile w przypadku zwykłych zmiennych będzie działać prawidłowo, to w przypadku np. wskaźników całkowicie zawiedzie, gdyż skopiowane zostaną adresy zawarte we wskaźnikach.
Dotychczas, wartości wewnętrznych zmiennych klasy były ustalane wewnątrz treści konstruktorów. Jednakże, każdy konstruktor powinien składać się z dwóch części, inicjalizującej i treści.
Większość zmiennych można zainicjować w dowolnej z tych części, albo poprzez inic-jalizację w części inicjalizującej, albo przez przypisanie wartości w treści konstruktora. Jednak bardziej elegancko i bardziej efektywnie jest wykorzystać do tego część inicjalizującą. Oto przykład prawidłowej inicjalizacji zmiennych wewnętrznych:
KOT(): // nazwa konstruktora i parametry
jegoWiek(5), // lista inicjalizacji
j egoWaga(8)
{ } // treść konstruktora
Po nawiasie zamykającym listę parametrów konstruktora postaw dwukropek. Następnie wpisz nazwę zmiennej i w nawiasach podaj wyrażenie, którego wartość ma być nadana tej zmiennej. Inicjalizację zmiennych oddzielaj przecinkami. Pamiętaj, że referencje i stale muszą być inicjalizowane, nie można im przypisywać wartości. W celu nadania im wartości trzeba wykorzystać metodę podaną powyżej. Powiedzieliśmy sobie, że inicjalizacja zmiennych wewnętrznych jest bardziej efektywna niż przypisywanie im wartości. Żeby to wytłumaczyć musimy najpierw dokładniej poznać zasady działania konstruktora kopiującego.
Podobnie jak w przypadku zwykłego konstruktora i destruktora, kompilator dostarcza również kopiujący konstruktor domyślny. Konstruktor kopiujący jest wywoływany w momencie tworzenia kopii obiektu danej klasy.
Kiedy obiekt jest przekazywany przez wartość, jako parametr lub ewentualnie wartość zwracana, to jest wykonywana chwilowa, robocza kopia tego obiektu. Jeśli jest to obiekt klasy zdefiniowanej przez użytkownika, to jest wywoływany konstruktor kopiujący tej klasy.
Konstruktor kopiujący ma tylko jeden parametr: referencje do obiektu tej samej klasy. Dobrze jest deklarować ten parametr jako eonst, gdyż konstruktor kopiujący nie ma prawa zmieniać zwartości obiektu. Oto przykład deklaracji konstruktora kopiującego:
KOT(eonst KOT Skotek);
Konstruktor kopiujący z klasy KOT pobiera stałą referencję do istniejącego obiektu klasy KOT. Zadaniem tego konstruktora jest wykonanie w pamięci kopii obiektu kotek.
Domyślny (dostarczany przez kompilator) konstruktor kopiujący, wykonuje kopię każdej zmiennej wewnętrznej obiektu źródłowego i umieszcza w nowym obiekcie. Jest to bardzo „płytkie” kopiowanie i o ile w przypadku zwykłych zmiennych będzie działać prawidłowo, to w przypadku np. wskaźników całkowicie zawiedzie, gdyż skopiowane zostaną adresy zawarte we wskaźnikach.