Konstruktor kopiuj ˛
acy
Bogdan Kreczmer
ZPCiR IIAiR PWr
pokój 307 budynek C3
bogdan.kreczmer@pwr.wroc.pl
Copyright c
°
2005–2010 Bogdan Kreczmer
?
?
Niniejszy dokument zawiera materiały do wykładu na temat programowania obiektowego. Jest on udost ˛epniony pod
warunkiem wykorzystania wył ˛
acznie do własnych prywatnych potrzeb i mo˙ze on by´c kopiowany wył ˛
acznie w cało´sci, razem z
niniejsz ˛
a stron ˛
a tytułow ˛
a.
1
Klasy z polami wska´znikowymi
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
KopiaNapisu( ) { wNapis = NULL; }
∼
KopiaNapisu( ) { if ( wNapis) delete [ ] wNapis; }
const char
∗
Wez( )
const { return
wNapis; }
void Zmien( const char
∗
wTekst )
}; //. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
void KopiaNapisu::Zmien( const char
∗
wTekst );
{
if ( wNapis ) delete [ ] wNapis;
if ( wTekst && ( wNapis = new char [strlen(wTekst)+1] ) ) strcpy( wNapis, wTekst );
}
Konstruktor kopiuj ˛
acy
1
Klasy z polami wska´znikowymi
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
KopiaNapisu( ) { wNapis = NULL; }
∼
KopiaNapisu( ) { if ( wNapis) delete [ ] wNapis; }
const char
∗
Wez( )
const { return
wNapis; }
void Zmien( const char
∗
wTekst )
}; //. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
void KopiaNapisu::Zmien( const char
∗
wTekst );
{
if ( wNapis ) delete [ ] wNapis;
if ( wTekst && ( wNapis = new char [strlen(wTekst)+1] ) ) strcpy( wNapis, wTekst );
}
Klasa
KopiaNapisu ma dobrze zdefiniowany interfejs, który zabezpiecza j ˛
a przed przypadkowymi
zmianami pola
wNapis
oraz stowarzyszonego z ni ˛
a napisu.
Konstruktor kopiuj ˛
acy
2
Klasy z polami wska´znikowymi
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
KopiaNapisu( ) { wNapis = NULL; }
∼
KopiaNapisu( ) { if ( wNapis) delete [ ] wNapis; }
const char
∗
Wez( )
const { return
wNapis; }
void Zmien( const char
∗
wTekst );
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
void
Wyswietl
(
KopiaNapisu Ob ) { cout
<<
”Wyswietl: ”
<<
Ob.Wez( )
<<
endl; }
int main( )
{
KopiaNapisu Ob;
Ob.Zmien( ”Abu Ja’far Mohammed ibn Mûsâ al-Khowârizmi” );
cout
<<
”main 1: ”
<<
Ob.Wez( )
<<
endl;
Wyswietl(Ob);
cout
<<
”main 2: ”
<<
Ob.Wez( )
<<
endl
;
}
Konstruktor kopiuj ˛
acy
2
Klasy z polami wska´znikowymi
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
KopiaNapisu( ) { wNapis = NULL; }
∼
KopiaNapisu( ) { if ( wNapis) delete [ ] wNapis; }
const char
∗
Wez( )
const { return
wNapis; }
void Zmien( const char
∗
wTekst );
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
void
Wyswietl
(
KopiaNapisu Ob ) { cout
<<
”Wyswietl: ”
<<
Ob.Wez( )
<<
endl; }
int main( )
{
KopiaNapisu Ob;
Ob.Zmien( ”Abu Ja’far Mohammed ibn Mûsâ al-Khowârizmi” );
cout
<<
”main 1: ”
<<
Ob.Wez( )
<<
endl;
Wyswietl(Ob);
cout
<<
”main 2: ”
<<
Ob.Wez( )
<<
endl
;
}
Wynik działania:
main 1:
Abu Ja’far Mohammed ibn Musa al-Khowarizmi
Wyswietl:
Abu Ja’far Mohammed ibn Musa al-Khowarizmi
main 2:
Konstruktor kopiuj ˛
acy
2
Klasy z polami wska´znikowymi
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
KopiaNapisu( ) { wNapis = NULL; }
∼
KopiaNapisu( ) { if ( wNapis) delete [ ] wNapis; }
const char
∗
Wez( )
const { return
wNapis; }
void Zmien( const char
∗
wTekst );
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
void
Wyswietl
(
KopiaNapisu Ob ) { cout
<<
”Wyswietl: ”
<<
Ob.Wez( )
<<
endl; }
int main( )
{
KopiaNapisu Ob;
Ob.Zmien( ”Abu Ja’far Mohammed ibn Mûsâ al-Khowârizmi” );
cout
<<
”main 1: ”
<<
Ob.Wez( )
<<
endl;
Wyswietl(Ob);
cout
<<
”main 2: ”
<<
Ob.Wez( )
<<
endl
;
}
Wynik działania:
main 1:
Abu Ja’far Mohammed ibn Musa al-Khowarizmi
Wyswietl:
Abu Ja’far Mohammed ibn Musa al-Khowarizmi
main 2:
Co stało si ˛e z napisem ???
Abu Ja’far Mohammed ibn Mûsâ al-Khowârizmi – (780-850) arabski matematyk urodzony w Bagdadzie, jednym z jego najwa˙zniejszych dokona ´n
jest napisanie w 825 podr ˛ecznika pt. ”Kitab al jabr w’al-muqabala”. Słowo algebra pochodzi z tytułu tego podr ˛ecznika (al jabr). Natomiast słowo
algorytm pochodzi od jego nazwiska. Uwa˙zał, ˙ze ka˙zdy problem matematyczny mo˙zna rozwi ˛
aza´c w serii pojedynczych kroków.
Konstruktor kopiuj ˛
acy
3
Przekazywanie obiektów przez warto ´s ´c
Konstruktor kopiuj ˛
acy
3
Przekazywanie obiektów przez warto ´s ´c
Przekazaniu parametru wywołania funkcji/metody przez warto´s´c towarzyszy utworzenie jego kopii na
poziomie tej funkcji/metody. Istnienie kopii ko ´nczy si ˛e wraz z zako ´nczeniem działania funkcji/metody.
Konstruktor kopiuj ˛
acy
4
Przekazywanie obiektów przez warto ´s ´c
(obiekt z polem wska´znikowym)
Konstruktor kopiuj ˛
acy
4
Przekazywanie obiektów przez warto ´s ´c
(obiekt z polem wska´znikowym)
Przy tworzeniu kopii przepisana zostaje cała zawarto´s´c obiektu ł ˛
acznie z zawarto´sci ˛
a pól wska´zni-
kowych. Powoduje to, ˙ze dwa obiekty poł ˛
aczone s ˛
a poprzez wska´zniki z tymi samymi strukturami.
Konstruktor kopiuj ˛
acy
5
Przekazywanie obiektów przez warto ´s ´c
(destrukcja cz.1)
Konstruktor kopiuj ˛
acy
5
Przekazywanie obiektów przez warto ´s ´c
(destrukcja cz.1)
Destrukcja kopii obiektu poci ˛
aga za sob ˛
a destrukcj ˛e dynamicznych struktur z nim stowarzyszonych.
Usuni ˛ete zostaj ˛
a w ten sposób struktury, które pierwotnie nale˙zały do oryginału.
Konstruktor kopiuj ˛
acy
6
Przekazywanie obiektów przez warto ´s ´c
(destrukcja cz.1)
Konstruktor kopiuj ˛
acy
6
Przekazywanie obiektów przez warto ´s ´c
(destrukcja cz.1)
Destrukcja oryginału, po wcze´sniejszym niekontrolowanym usuni ˛eciu struktur stowarzyszonym z da-
nym obiektem, prowadzi do nieprzewidzianych skutków
(zwykle jest to:
segmentation fault
:-)
.
Konstruktor kopiuj ˛
acy
7
Przekazywanie obiektów przez warto ´s ´c
( konstruktor kopiuj ˛
acy )
Konstruktor kopiuj ˛
acy
7
Przekazywanie obiektów przez warto ´s ´c
( konstruktor kopiuj ˛
acy )
Implementacja konstruktora kopiuj ˛
acego pozwala na poprawne powielenie struktur stowarzyszonych
z oryginalnym obiektem. Tym samym zapewnia prawidłow ˛
a pó´zniejsz ˛
a destrukcj ˛e takiego obiektu.
Konstruktor kopiuj ˛
acy
8
Przekazywanie obiektów przez referencj ˛e
Konstruktor kopiuj ˛
acy
8
Przekazywanie obiektów przez referencj ˛e
Przekazywanie obiektu przez referencj ˛e pozwala unikn ˛
a´c tworzenia kopii obiektu, która czasem
mo˙ze by´c zb ˛edna.
Konstruktor kopiuj ˛
acy
9
Implementacja konstruktora kopiuj ˛
acego
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
KopiaNapisu( ) { wNapis = NULL; }
KopiaNapisu
(
const KopiaNapisu & Ob ) { wNapis = NULL; Zmien(Ob. wNapis); }
∼
KopiaNapisu( ) { if ( wNapis) delete [ ] wNapis; }
const char
∗
Wez( )
const { return
wNapis; }
void Zmien( const char
∗
wTekst );
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
void Wyswietl( KopiaNapisu Ob ) { cout
<<
”Wyswietl: ”
<<
Ob.Wez( )
<<
endl; }
int main( )
{
KopiaNapisu Ob;
Ob.Zmien( ”Abu Ja’far Mohammed ibn Mûsâ al-Khowârizmi” );
cout
<<
”main 1: ”
<<
Ob.Wez( )
<<
endl;
Wyswietl(Ob);
cout
<<
”main 2: ”
<<
Ob.Wez( )
<<
endl
;
}
Konstruktor kopiuj ˛
acy
9
Implementacja konstruktora kopiuj ˛
acego
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
KopiaNapisu( ) { wNapis = NULL; }
KopiaNapisu
(
const KopiaNapisu & Ob ) { wNapis = NULL; Zmien(Ob. wNapis); }
∼
KopiaNapisu( ) { if ( wNapis) delete [ ] wNapis; }
const char
∗
Wez( )
const { return
wNapis; }
void Zmien( const char
∗
wTekst );
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
void Wyswietl( KopiaNapisu Ob ) { cout
<<
”Wyswietl: ”
<<
Ob.Wez( )
<<
endl; }
int main( )
{
KopiaNapisu Ob;
Ob.Zmien( ”Abu Ja’far Mohammed ibn Mûsâ al-Khowârizmi” );
cout
<<
”main 1: ”
<<
Ob.Wez( )
<<
endl;
Wyswietl(Ob);
cout
<<
”main 2: ”
<<
Ob.Wez( )
<<
endl
;
}
Wynik działania:
main 1:
Abu Ja’far Mohammed ibn Musa al-Khowarizmi
Wyswietl:
Abu Ja’far Mohammed ibn Musa al-Khowarizmi
main 2:
Abu Ja’far Mohammed ibn Musa al-Khowarizmi
Konstruktor kopiuj ˛
acy
9
Implementacja konstruktora kopiuj ˛
acego
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
KopiaNapisu( ) { wNapis = NULL; }
KopiaNapisu
(
const KopiaNapisu & Ob ) { wNapis = NULL; Zmien(Ob. wNapis); }
∼
KopiaNapisu( ) { if ( wNapis) delete [ ] wNapis; }
const char
∗
Wez( )
const { return
wNapis; }
void Zmien( const char
∗
wTekst );
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
void Wyswietl( KopiaNapisu Ob ) { cout
<<
”Wyswietl: ”
<<
Ob.Wez( )
<<
endl; }
int main( )
{
KopiaNapisu Ob;
Ob.Zmien( ”Abu Ja’far Mohammed ibn Mûsâ al-Khowârizmi” );
cout
<<
”main 1: ”
<<
Ob.Wez( )
<<
endl;
Wyswietl(Ob);
cout
<<
”main 2: ”
<<
Ob.Wez( )
<<
endl
;
}
Wynik działania:
main 1:
Abu Ja’far Mohammed ibn Musa al-Khowarizmi
Wyswietl:
Abu Ja’far Mohammed ibn Musa al-Khowarizmi
main 2:
Abu Ja’far Mohammed ibn Musa al-Khowarizmi
Implementacja konstruktora kopiuj ˛
acego zapewnia wła´sciwe przekazywanie parametru i nie tylko.
Konstruktor kopiuj ˛
acy
10
Implementacja konstruktora kopiuj ˛
acego
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
KopiaNapisu( ) { wNapis = NULL; }
KopiaNapisu( const KopiaNapisu & Ob ) { wNapis = NULL; Zmien(Ob. wNapis); }
∼
KopiaNapisu( ) { if ( wNapis) delete [ ] wNapis; }
const char
∗
Wez( )
const { return
wNapis; }
void Zmien( const char
∗
wTekst );
}; //. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
int main( )
{
KopiaNapisu Ob1;
Ob1.Zmien(”Hippasus z Metapontum”);
{
KopiaNapisu Ob2;
Ob2 = Ob1
;
cout
<<
”Ob1: ”
<<
Ob1.Wez( )
<<
endl;
cout
<<
”Ob2: ”
<<
Ob2.Wez( )
<<
endl;
}
cout
<<
”Ob1: ”
<<
Ob1.Wez( )
<<
endl
;
}
Konstruktor kopiuj ˛
acy
10
Implementacja konstruktora kopiuj ˛
acego
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
KopiaNapisu( ) { wNapis = NULL; }
KopiaNapisu( const KopiaNapisu & Ob ) { wNapis = NULL; Zmien(Ob. wNapis); }
∼
KopiaNapisu( ) { if ( wNapis) delete [ ] wNapis; }
const char
∗
Wez( )
const { return
wNapis; }
void Zmien( const char
∗
wTekst );
}; //. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
int main( )
{
KopiaNapisu Ob1;
Ob1.Zmien(”Hippasus z Metapontum”);
{
KopiaNapisu Ob2;
Ob2 = Ob1
;
cout
<<
”Ob1: ”
<<
Ob1.Wez( )
<<
endl;
cout
<<
”Ob2: ”
<<
Ob2.Wez( )
<<
endl;
}
cout
<<
”Ob1: ”
<<
Ob1.Wez( )
<<
endl
;
}
Wynik działania:
Ob1:
Hippasus z Metapontum
Ob2:
Hippasus z Metapontum
Ob1:
Konstruktor kopiuj ˛
acy
10
Implementacja konstruktora kopiuj ˛
acego
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
KopiaNapisu( ) { wNapis = NULL; }
KopiaNapisu( const KopiaNapisu & Ob ) { wNapis = NULL; Zmien(Ob. wNapis); }
∼
KopiaNapisu( ) { if ( wNapis) delete [ ] wNapis; }
const char
∗
Wez( )
const { return
wNapis; }
void Zmien( const char
∗
wTekst );
}; //. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
int main( )
{
KopiaNapisu Ob1;
Ob1.Zmien(”Hippasus z Metapontum”);
{
KopiaNapisu Ob2;
Ob2 = Ob1
;
cout
<<
”Ob1: ”
<<
Ob1.Wez( )
<<
endl;
cout
<<
”Ob2: ”
<<
Ob2.Wez( )
<<
endl;
}
cout
<<
”Ob1: ”
<<
Ob1.Wez( )
<<
endl
;
}
Wynik działania:
Ob1:
Hippasus z Metapontum
Ob2:
Hippasus z Metapontum
Ob1:
Czemu ponownie brakuje tekstu?
Konstruktor kopiuj ˛
acy
11
Implementacja operacji przypisania
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
. . .
KopiaNapisu &
operator =
(
const KopiaNapisu & Ob )
{ Zmien( Ob. wNapis );
return
∗
this ; }
. . .
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
int main( )
{
KopiaNapisu Ob1;
Ob1.Zmien(”Hippasus z Metapontum”);
{
KopiaNapisu Ob2;
Ob2 = Ob1
;
cout
<<
”Ob1: ”
<<
Ob1.Wez( )
<<
endl;
cout
<<
”Ob2: ”
<<
Ob2.Wez( )
<<
endl;
}
cout
<<
”Ob1: ”
<<
Ob1.Wez( )
<<
endl
;
}
Konstruktor kopiuj ˛
acy
11
Implementacja operacji przypisania
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
. . .
KopiaNapisu &
operator =
(
const KopiaNapisu & Ob )
{ Zmien( Ob. wNapis );
return
∗
this ; }
. . .
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
int main( )
{
KopiaNapisu Ob1;
Ob1.Zmien(”Hippasus z Metapontum”);
{
KopiaNapisu Ob2;
Ob2 = Ob1
;
cout
<<
”Ob1: ”
<<
Ob1.Wez( )
<<
endl;
cout
<<
”Ob2: ”
<<
Ob2.Wez( )
<<
endl;
}
cout
<<
”Ob1: ”
<<
Ob1.Wez( )
<<
endl
;
}
Wynik działania:
Ob1:
Hippasus z Metapontum
Ob2:
Hippasus z Metapontum
Ob1:
Hippasus z Metapontum
Konstruktor kopiuj ˛
acy
11
Implementacja operacji przypisania
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
. . .
KopiaNapisu &
operator =
(
const KopiaNapisu & Ob )
{ Zmien( Ob. wNapis );
return
∗
this ; }
. . .
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
int main( )
{
KopiaNapisu Ob1;
Ob1.Zmien(”Hippasus z Metapontum”);
{
KopiaNapisu Ob2;
Ob2 = Ob1
;
cout
<<
”Ob1: ”
<<
Ob1.Wez( )
<<
endl;
cout
<<
”Ob2: ”
<<
Ob2.Wez( )
<<
endl;
}
cout
<<
”Ob1: ”
<<
Ob1.Wez( )
<<
endl
;
}
Wynik działania:
Ob1:
Hippasus z Metapontum
Ob2:
Hippasus z Metapontum
Ob1:
Hippasus z Metapontum
Stosowanie pól wska´znikowych wymaga prawie zawsze implementacji konstruktora kopiuj ˛
acego i
przeci ˛
a˙zenia operatora przypisania.
Konstruktor kopiuj ˛
acy
12
Konstruktor kopiuj ˛
acy
(raz jeszcze)
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
. . .
KopiaNapisu( const KopiaNapisu & Ob ):
wNapis(NULL)
{ cout
<<
”++ Konstruktor kopiujacy”
<<
endl; Zmien(Ob. wNapis); }
. . .
KopiaNapisu &
operator =
(
const KopiaNapisu & Ob ) { Zmien( Ob. wNapis ); }
. . .
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
int main( )
{
KopiaNapisu Ob1;
Ob1.Zmien(”Ten tekst nic nie znaczy ;-)”);
KopiaNapisu Ob2(Ob1)
;
KopiaNapisu Ob3 = Ob1
;
}
Konstruktor kopiuj ˛
acy
12
Konstruktor kopiuj ˛
acy
(raz jeszcze)
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
. . .
KopiaNapisu( const KopiaNapisu & Ob ):
wNapis(NULL)
{ cout
<<
”++ Konstruktor kopiujacy”
<<
endl; Zmien(Ob. wNapis); }
. . .
KopiaNapisu &
operator =
(
const KopiaNapisu & Ob ) { Zmien( Ob. wNapis ); }
. . .
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
int main( )
{
KopiaNapisu Ob1;
Ob1.Zmien(”Ten tekst nic nie znaczy ;-)”);
KopiaNapisu Ob2(Ob1)
;
KopiaNapisu Ob3 = Ob1
;
}
Wynik działania:
++ Konstruktor kopiujacy
++ Konstruktor kopiujacy
Konstruktor kopiuj ˛
acy
12
Konstruktor kopiuj ˛
acy
(raz jeszcze)
class KopiaNapisu { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char
∗
wNapis;
public :
. . .
KopiaNapisu( const KopiaNapisu & Ob ):
wNapis(NULL)
{ cout
<<
”++ Konstruktor kopiujacy”
<<
endl; Zmien(Ob. wNapis); }
. . .
KopiaNapisu &
operator =
(
const KopiaNapisu & Ob ) { Zmien( Ob. wNapis ); }
. . .
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
int main( )
{
KopiaNapisu Ob1;
Ob1.Zmien(”Ten tekst nic nie znaczy ;-)”);
KopiaNapisu Ob2(Ob1)
;
KopiaNapisu Ob3 = Ob1
;
}
Wynik działania:
++ Konstruktor kopiujacy
++ Konstruktor kopiujacy
Przy inicjalizacji zawsze i wył ˛
acznie wywoływane s ˛
a konstruktory. W szczególno´sci zapis operacji
przypisania odpowiada uruchomieniu operatora kopiuj ˛
acego.
Konstruktor kopiuj ˛
acy
13
Klasa z polami referencyjnymi
class KlasaZReferencja { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
public :
int & PoleRef;
int
PoleNor;
KlasaZReferencja( ): PoleRef( PoleNor ) { }
KlasaZReferencja( int & Zm ): PoleRef( Zm ) { }
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
int main( )
{
KlasaZReferencja
Ob1, Ob2(Ob1. PoleNor);
KlasaZReferencja
hhh
hhh
hhh
((
((
((
((
(
Ob3(Ob1);
hhh
hhh
hhh
((
((
((
((
(
Ob1 = Ob2;
}
Konstruktor kopiuj ˛
acy
13
Klasa z polami referencyjnymi
class KlasaZReferencja { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
public :
int & PoleRef;
int
PoleNor;
KlasaZReferencja( ): PoleRef( PoleNor ) { }
KlasaZReferencja( int & Zm ): PoleRef( Zm ) { }
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
int main( )
{
KlasaZReferencja
Ob1, Ob2(Ob1. PoleNor);
KlasaZReferencja
hhh
hhh
hhh
((
((
((
((
(
Ob3(Ob1);
hhh
hhh
hhh
((
((
((
((
(
Ob1 = Ob2;
}
W przypadku klas zawieraj ˛
acych pola referencyjne zarówno konstruktor kopiuj ˛
acy jak te˙z operator
przypisania nie s ˛
a domy´slnie definiowane.
Konstruktor kopiuj ˛
acy
14
Klasa z polami referencyjnymi
(raz jeszcze)
class KlasaZReferencja { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
public :
int & PoleRef;
int
PoleNor;
KlasaZReferencja( ): PoleRef( PoleNor ) { }
KlasaZReferencja( int & Zm ): PoleRef( Zm ) { }
KlasaZReferencja( const KlasaZReferencja & Ob ): PoleRef( PoleNor) { . . . }
KlasaZReferencja & operator = (const KlasaZReferencja & Ob ) { . . . }
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
int main( )
{
KlasaZReferencja
Ob1, Ob2(Ob1. PoleNor);
KlasaZReferencja
Ob3(Ob1)
;
Ob1 = Ob2
;
}
Konstruktor kopiuj ˛
acy
14
Klasa z polami referencyjnymi
(raz jeszcze)
class KlasaZReferencja { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
public :
int & PoleRef;
int
PoleNor;
KlasaZReferencja( ): PoleRef( PoleNor ) { }
KlasaZReferencja( int & Zm ): PoleRef( Zm ) { }
KlasaZReferencja( const KlasaZReferencja & Ob ): PoleRef( PoleNor) { . . . }
KlasaZReferencja & operator = (const KlasaZReferencja & Ob ) { . . . }
}; // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
int main( )
{
KlasaZReferencja
Ob1, Ob2(Ob1. PoleNor);
KlasaZReferencja
Ob3(Ob1)
;
Ob1 = Ob2
;
}
Zdefiniowanie konstruktora kopiuj ˛
acego i operatora przypisania jest warunkiem koniecznym akcep-
tacji przez kompilator wy˙zej przedstawionych operacji. Dotyczy to równie˙z przekazywania obiektu
przez warto´s´c jako parametru wywołania oraz jego zwracania przez funkcj ˛e/metod ˛e.
Konstruktor kopiuj ˛
acy
15
Podsumowanie
(pola wska´znikowe)
•
W przypadku klas, w których zdefiniowane s ˛
a pola wska´znikowe, mo˙ze ko-
niecznym okaza´c si ˛e zdefiniowanie konstruktora kopiuj ˛
acego oraz przeci ˛
a-
˙zenie operatora przypisania. Jest to niezb ˛edne wtedy, gdy obiekty tej klasy
stowarzyszone s ˛
a ze strukturami tworzonymi dynamicznie i usuwanymi w
destruktorze.
Konstruktor kopiuj ˛
acy
15
Podsumowanie
(pola wska´znikowe)
•
W przypadku klas, w których zdefiniowane s ˛
a pola wska´znikowe, mo˙ze ko-
niecznym okaza´c si ˛e zdefiniowanie konstruktora kopiuj ˛
acego oraz przeci ˛
a-
˙zenie operatora przypisania. Jest to niezb ˛edne wtedy, gdy obiekty tej klasy
stowarzyszone s ˛
a ze strukturami tworzonymi dynamicznie i usuwanymi w
destruktorze.
•
Je˙zeli w destruktorze stowarzyszone z danym obiektem struktury danych nie
s ˛
a poddawane destrukcji, to na ogół mo˙zna ograniczy´c si ˛e do domy´slnej im-
plementacji konstruktora kopiuj ˛
acego i operatora przypisania.
Konstruktor kopiuj ˛
acy
16
Podsumowanie
(pola referencyjne)
•
W klasach, w których definiowane s ˛
a pola referencyjne nie istnieje domy´slna
implementacja konstruktora kopiuj ˛
acego i operatora przypisania. Wynika to
z fakty, ˙ze zwykłe przepisanie bajt po bajcie zawarto´sci obiektów zmieniałoby
referencje. Z definicji za´s referencji wynika, ˙ze w trakcie swojego istnienia nie
mo˙ze ona ulega´c zmianom.
Konstruktor kopiuj ˛
acy
16
Podsumowanie
(pola referencyjne)
•
W klasach, w których definiowane s ˛
a pola referencyjne nie istnieje domy´slna
implementacja konstruktora kopiuj ˛
acego i operatora przypisania. Wynika to
z fakty, ˙ze zwykłe przepisanie bajt po bajcie zawarto´sci obiektów zmieniałoby
referencje. Z definicji za´s referencji wynika, ˙ze w trakcie swojego istnienia nie
mo˙ze ona ulega´c zmianom.
•
Je˙zeli obiekty klasy zawieraj ˛
acej pola referencyjne maj ˛
a by´c przekazywane
jako parametr wywołania funkcji/metody lub przez nie zwracane lub te˙z w
sposób jawny ma by´c wywoływany konstruktor kopiuj ˛
acy, to jego zdefiniowa-
nie jest bezwzgl ˛ednie konieczne.
Konstruktor kopiuj ˛
acy
16
Podsumowanie
(pola referencyjne)
•
W klasach, w których definiowane s ˛
a pola referencyjne nie istnieje domy´slna
implementacja konstruktora kopiuj ˛
acego i operatora przypisania. Wynika to
z fakty, ˙ze zwykłe przepisanie bajt po bajcie zawarto´sci obiektów zmieniałoby
referencje. Z definicji za´s referencji wynika, ˙ze w trakcie swojego istnienia nie
mo˙ze ona ulega´c zmianom.
•
Je˙zeli obiekty klasy zawieraj ˛
acej pola referencyjne maj ˛
a by´c przekazywane
jako parametr wywołania funkcji/metody lub przez nie zwracane lub te˙z w
sposób jawny ma by´c wywoływany konstruktor kopiuj ˛
acy, to jego zdefiniowa-
nie jest bezwzgl ˛ednie konieczne.
•
W przypadku, gdy ma by´c wykonywana operacja przypisania, konieczne jest
wówczas zdefiniowanie operatora przypisania.
Konstruktor kopiuj ˛
acy
16
Podsumowanie
(pola referencyjne)
•
W klasach, w których definiowane s ˛
a pola referencyjne nie istnieje domy´slna
implementacja konstruktora kopiuj ˛
acego i operatora przypisania. Wynika to
z fakty, ˙ze zwykłe przepisanie bajt po bajcie zawarto´sci obiektów zmieniałoby
referencje. Z definicji za´s referencji wynika, ˙ze w trakcie swojego istnienia nie
mo˙ze ona ulega´c zmianom.
•
Je˙zeli obiekty klasy zawieraj ˛
acej pola referencyjne maj ˛
a by´c przekazywane
jako parametr wywołania funkcji/metody lub przez nie zwracane lub te˙z w
sposób jawny ma by´c wywoływany konstruktor kopiuj ˛
acy, to jego zdefiniowa-
nie jest bezwzgl ˛ednie konieczne.
•
W przypadku, gdy ma by´c wykonywana operacja przypisania, konieczne jest
wówczas zdefiniowanie operatora przypisania.
•
Je˙zeli wy˙zej wymienione operacje nie b ˛ed ˛
a wykonywane, to nie ma potrzeby
definiowania zarówno konstruktora kopiuj ˛
acego, jak te˙z operatora przypisa-
nia.
Konstruktor kopiuj ˛
acy