Przypisanie i inicjowanie elementów członkowskich
Metody domyślnego przypisywania i inicjowania to odpowiednio "przypisanie memberwise" i "inicjowanie memberwise".Przypisywanie memberwise składa się z kopiowania jednego obiektu do drugiego, jeden element członkowski po drugim, tak jakby każdy element był przypisywany indywidualnie.Inicjowanie memberwise składa się z kopiowania jednego obiektu do drugiego, jeden element członkowski po drugim, tak jakby każdy element był inicjowany indywidualnie.Podstawową różnicą między tymi dwoma jest to, że przypisanie memberwise wywołuje operator przypisania każdego członka (operator=), podczas gdy inicjowanie memberwise wywołuje konstruktora kopii każdego elementu członkowskiego.
Przypisywanie memberwise jest wykonywane tylko przez operator przypisania zadeklarowany w formie:
type**&** type :: operator=( [const | volatile] type**&** )
Nie można wygenerować domyślnych operatorów przypisania dla przypisania memberwise, jeśli występuje którykolwiek z następujących warunków:
Klasa członkowska posiada elementy członkowskie const.
Klasa członkowska ma odwołania członkowskie.
Klasa członkowska lub jej klasa podstawowa ma prywatny operator przypisania (operator=).
Klasa podstawowa lub klasa członkowska nie ma żadnego operatora przypisania (operator=).
Nie można wygenerować domyślnych konstruktorów kopii dla inicjowania memberwise, jeśli klasa lub jedna z jej klas podstawowych ma prywatny konstruktor kopii lub jeśli występuje którykolwiek z następujących warunków:
Klasa członkowska posiada elementy członkowskie const.
Klasa członkowska ma odwołania członkowskie.
Klasa członkowska lub jej klasa podstawowa posiada prywatny konstruktor kopii.
Klasa podstawowa lub klasa członkowska nie posiada konstruktora kopii.
Domyślne operatory przypisania i konstruktory kopii dla danej klasy są zawsze zadeklarowane, ale nie są zdefiniowane, chyba że spełnione są oba następujące warunki:
Klasa nie dostarcza zdefiniowanej przez użytkownika funkcji dla tej kopii.
Program wymaga, aby funkcja była obecna.Wymaganie to istnieje, jeśli wystąpi sytuacja, w której przypisanie lub inicjowanie wymaga kopiowania memberwise lub jeśli jest przyjęty adres funkcji klasy operator=.
Jeśli nie są spełnione oba te warunki, kompilator nie musi generować kodu dla domyślnego operatora przypisania i funkcji konstruktora kopii (wykluczenie takiego kodu jest optymalizacją wykonywaną przez kompilator Microsoft C++).W szczególności, jeżeli klasa deklaruje zdefiniowany przez użytkownika operator= pobierający argument typu "odwołanie do nazwa-klasy", nie jest generowany żaden domyślny operator przypisania.Jeśli klasa deklaruje konstruktor kopii, nie jest generowany domyślny konstruktor kopii.
W związku z tym, dla danej klasy A, zawsze są obecne następujące deklaracje:
// Implicit declarations of copy constructor
// and assignment operator.
A::A( const A& );
A& A::operator=( const A& );
Definicje są dostarczane tylko wtedy, gdy jest to wymagane (zgodnie z powyższymi kryteriami).Funkcje konstruktora kopii pokazane w poprzednim przykładzie są traktowane jako publiczne funkcje członkowskie klasy.
Domyślne operatory przypisania zezwalają obiektom danej klasy na przypisywanie do obiektów publicznych typu klasy podstawowej.Rozważ następujący kod:
Przykład
// spec1_memberwise_assignment_and_initialization.cpp
#include<stdio.h>
class Account
{
protected:
int _balance;
public:
int getBalance()
{
return _balance;
}
};
class Checking : public Account
{
private:
int _fOverdraftProtect;
public:
Checking(int balance, int fOverdraftProtect)
{
_balance = balance;
_fOverdraftProtect = fOverdraftProtect;
}
};
int main()
{
Account account;
Checking checking(1000, 1);
account = checking;
printf_s("Account balance = %d\n", account.getBalance());
}
Komentarz
W poprzednim przykładzie wybranym operatorem przypisania jest Account::operator=.Ponieważ domyślnie funkcja operator= przyjmuje argument typu Account& (odwołanie do Account), Account, podobiekt checking jest kopiowany do account; fOverdraftProtect nie jest kopiowany.