14.6 Konstruktory

W zasadzie każda klasa musi mieć konstruktor: funkcję wywoływaną podczas kreowania nowego obiektu danej klasy. Jeśli sami żadnego konstruktora nie zdefiniowaliśmy, to możemy zakładać, że system dostarczy własny konstuktor domyślny, który jest publiczny, nie ma żadnych parametrów i nie wykonuje żadnych czynności.

Jeśli jakikolwiek konstruktor został w klasie zdefiniowany, to konstruktor domyślny nie będzie kreowany automatycznie. Konstruktor jest konstruktorem domyślnym wtedy i tylko wtedy gdy może być wywołany bez żadnych argumentów.

Nie znaczy to, że konstruktor domyślny koniecznie musi być zdefiniowany jako funkcja bezparametrowa; może mieć dowolną liczbę parametrów, ale jeśli je ma, to wszystkie muszą mieć zdefiniowane wartości domyślne (patrz rozdział o argumentach domyślnych ).

W klasie może oczywiście istnieć tylko jeden konstruktor domyślny. Jeśli został wygenerowany automatycznie, to, jak już mówiliśmy, jego ciało jest puste (czyli „nic nie robi”), a jego dostępność jest typu public.

Konstruktor (niekoniecznie domyślny) jest wywoływany automatycznie wyłącznie podczas tworzenia obiektu (ściśle mówiąc, na zakończenie tego procesu); nie można go wywołać „ręcznie”, jak normalnej metody, na rzecz obiektu już istniejącego.

Nazwa konstruktora musi być identyczna z nazwą klasy; wielkość liter, oczywiście, jest przy tym ważna.

Konstruktor nie może być funkcją rezultatową; mimo to deklarując/definiując go nie wolno podać jako typu zwracanego void — typu zwracanego nie podajemy w ogóle.

Konstruktory, jak inne funkcje, mogą mieć parametry domyślne. Można nawet powiedzieć, że parametry domyślne są właśnie w przypadku konstruktorów szczególnie przydatne i często stosowane.

Konstruktory mogą też być przeładowywane (przeciążane), jak normalne funkcje. Wszystkie mają w danej klasie taką samą nazwę: taką jak nazwa tej klasy. Jeśli jest ich kilka, to podczas tworzenia obiektu wybierany jest ten „najbardziej pasujący", zgodnie z zasadami obowiązującymi dla wywoływania funkcji przeciążonych (patrz rozdział o przeciążaniu funkcji ).

Zauważmy, że jeśli zmienne obiektowe definiujemy w zakresie globalnym, a więc poza definicjami funkcji, albo jeśli takie zmienne są polami statycznymi klasy, to konstruktory dla tych obiektów zostaną wywołane w czasie tworzenia tych obiektów, a więc jeszcze przed wywołaniem funkcji main! Obiekty globalne są tworzone w kolejności, w jakiej są w programie definiowane, a zatem w takiej też kolejności będą wywoływane konstruktory.

W czasie wykonywania konstruktora obiekt jest już skonstruowany, to znaczy został fizycznie utworzony w pamięci, jak również, co bardzo ważne, zostały już utworzone wszystkie jego składowe opisane polami klasy. Składowe te tworzone są w kolejności takiej, w jakiej zostały zadeklarowane w definicji klasy/struktury.

Ponieważ obiekt w zasadzie już istnieje, gdy konstruktor rozpoczyna działanie, ma sens posługiwanie się wewnątrz konstruktora wskaźnikiem this wskazującym na tworzony obiekt. Tym niemniej, do obiektu można się na razie odwoływać tylko z wnętrza konstruktora. Dopóki konstruktor nie zakończy swej pracy, tworzony obiekt jest niedostępny z zewnątrz; ma to znaczenie na przykład w programach wielowątkowych.

T.R. Werner, 25 lutego 2017; 22:31