• Nie Znaleziono Wyników

Wykład 2

N/A
N/A
Protected

Academic year: 2021

Share "Wykład 2"

Copied!
1
0
0

Pełen tekst

(1)

Wykład 2

1. Przeciążanie funkcji niezależnych, przekazywanie parametrów obiektowych przez wartość, referencję oraz wskaźnik

2. Przeciążanie funkcji składowych, przekazywanie parametrów obiektowych przez wartość, referencję oraz wskaźnik

3. Przeciążanie konstruktora - konstruktor bezparametrowy i z parametrami 4. Konstruktor z parametrami domniemanymi

5. Zwracanie wyniku działania funkcji przez obiekt. Autoreferencja - wskaźnik this

6. Jawny konstruktor kopiowania 7. Inicjowanie obiektów

8. Tworzenie i inicjowanie obiektów posiadających obiekty składowe - konstruktory wieloargumentowe

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 21

(2)

1. Przeciążanie funkcji niezależnych, przekazywanie parametrów obiektowych przez wartość, referencję oraz wskaźnik

1.1. Przeciążanie funkcji - nadawanie tej samej nazwy w tym samym zasięgu dla różnych operacji (różne ciała funkcji) na różnych typach danych (różne listy parametrów funkcji - liczba i typ parametrów) np.

funkcja wyswietl.

Przy przeciążaniu funkcji wybór egzemplarza funkcji następuje według następujących zasad kolejności konwersji (najlepszego dopasowania):

· Ścisła zgodność: nie trzeba stosować żadnych konwersji (np. nazwa tablicy na wskaźnik elementu tablicy, nazwa funkcji na wskaźnik do funkcji),

· Zgodność przy zastosowaniu promowania w zakresie typów całkowitych (np. char na int, short na int i ich odpowiedniki bez znaku) oraz typów zmiennoprzecinkowych np. float na double

· Zgodność przy zastosowaniu standardowych konwersji (np. int na double, klasa pochodna* na podstawowa*, unsigned int na int)

· Zgodność przy zastosowaniu konwersji zdefiniowanych prze użytkownika

· Zgodność przy zastosowaniu wielokropka .... w deklaracji funkcji Uwagi:

· Przy wywołaniu funkcje z parametrami przekazywanymi przez referencję nie są rozróżniane z parametrami przekazywanymi przez wartość, stąd czasem stosuje się sztuczne zabiegi (np. dodatkowy argument)

np.

void f(int&) i

void f(int) ® void f(int&, int) i void f(int)

· Funkcje, które różnią się jedynie typem zwracanej wartości, nie mogą mieć tej samej nazwy np. int f() i double f()

· Obiekty przekazane jako parametry funkcji niezależnych udostępniają jedynie swoje składowe publiczne (public)

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 22

(3)

1.2. Przekazywanie parametrów przez:

Sposób Uwagi Przykład

Referencja na stos przekazywany jest niejawnie adres obiektu aktualnego i nie są tworzone

obiekty tymczasowe w

przypadku zgodności typów parametrów aktualnego i formalnego

void wyswietl(punkt &p)

Wskaźnik na stos przekazywany jest jawnie adres obiektu aktualnego i nie są tworzone obiekty automatyczne

void wyswietl(punkt *p)

Wartość na stosie tworzony jest obiekt automatyczny za pomocą konstruktora kopiującego (jawnego lub domyślnego- wykład 1). Po zakończeniu bloku obiektu automatycznego ({}) w funkcji usuwa się obiekt za pomocą destruktora (jawnego lub domyślnego-wykład 1)

void wyswietl(punkt p)

#include <iostream.h>

#include "punkt2_1.h" //plik nagłówkowy i modułowy jak w p. 7 wykład 1

void wyswietl(punkt&); // prototypy niezależnych funkcji przeciążonych wyswietl

void wyswietl(punkt*);

void wyswietl(punkt, char);

void wyswietl(float);

void wyswietl(int);

void main()

{{ punkt p1(1, 2), p2(2, 3);

wyswietl(p1); wyswietl(p2); //p1 i p2 przekazane przez referencje wyswietl(&p1); wyswietl(&p2); //p1 i p2 przekazane przez wskaźnik

wyswietl(p1, 32); wyswietl(p2, 32); // p1 i p2 przekazane przez wartość 32 - spacja,

wyswietl(punkt::liczba_punktow()); //liczba obiektów równa 0 - źle!

wyswietl(p1.odleglosc(p2)); //p1 i p2 przekazane przez referencje

wyswietl(p2.odleglosc(p1));

} //tutaj koniec bloku i zostają usunięte wszystkie obiekty powołane w poprzednim bloku

wyswietl(punkt::liczba_punktow()); } //liczba obiektów równa -2 - źle!

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 23

(4)

//definicje funkcji przeciążonych

void wyswietl(punkt& p) //przekazywanie przez referencję {/*Na stos zostanie przekazany niejawnie adres aktualnego obiektu p. Wszystkie operacje są wykonywane na obiekcie aktualnym*/

cout<<"Przekazanie przez referencje punktu o ";

cout <<"wspolrzednych: " << p.odcieta() << " "<< p.rzedna() << ’\n’;}

void wyswietl(punkt *p) //przekazywanie przez wskaźnik

{/*Na stos zostanie przekazany jawny adres obiektu aktualnego podstawionego pod p. Wyłuskanie składowych obiektu następuje za pomocą operatora wyboru p® lub (*p). Wszystkie operacje są wykonywane na parametrze aktualnym.*/

cout<<"Przekazanie przez wskaznik punktu o ";

cout <<"wspolrzednych: " << p->odcieta() << " "<< p->rzedna() << '\n';

//lub cout <<"wspolrzednych: "<<(*).podcieta() << " "<<(* p).rzedna() << '\n';}

void wyswietl(punkt p, char) //przekazywanie przez wartość

{/*Zostanie wywołany niejawny konstruktor kopiujący do utworzenia obiektu automatycznego na stosie, kopiujący niestatyczne pola przekazywanego obiektu p, bez inkrementacji pola ile_punktow. Wszystkie operacje są wykonywane na obiekcie automatycznym. W jawnym konstruktorze można odwoływać się do pola statycznego. */

cout<<"Przekazanie przez wartosc punktu o ";

cout <<"wspolrzednych: „ << p.odcieta() << „ „<< p.rzedna();

/*tutaj zostanie wywołany destruktor jawny, zmniejszający o 1 liczbę obiektów pamiętanych w globalnym polu statycznym klasy punkt*/ }

void wyswietl(float w) { cout <<"Odleglosc: " << w << ’\n’;}

void wyswietl(int w) { cout <<"Liczba punktow: " << w << ’\n’;}

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 24

(5)

2. Przeciążanie funkcji składowych, przekazywanie parametrów obiektowych przez wartość, referencję oraz wskaźnik

Zasady przeciążania funkcji składowych są identyczne z zasadami przeciążania funkcji niezależnych

Obiekty przekazane jako parametry funkcji składowych swojej klasy udostępniają swoje składowe prywatne i zabezpieczone (private i protected), w pozostałych wypadkach jedynie składowe publiczne (public).

#include <iostream.h>

#include "punkt2_2.h"

#include <conio.h>

void wyswietl(punkt&);

void wyswietl(float);

void wyswietl(int);

void main() { clrscr();

{ punkt p1(1, 2), p2(2, 3);

/*przekazywanie przez referencję - Na stos zostanie przekazany niejawnie adres aktualnego obiektu p1 lub p2. Wszystkie operacje są wykonywane na obiekcie aktualnym*/

wyswietl(p1);

wyswietl(p2);

wyswietl(p1.odleglosc(p2));

wyswietl(p2.odleglosc(p1));

wyswietl(punkt::liczba_punktów()); // 2 obiekty

/*przekazywanie przez wskaźnik - Na stos zostanie przekazany jawny adres obiektu &p1 lub

&p2. Wszystkie operacje są wykonywane na parametrze aktualnym.*/

wyswietl(p1.odleglosc(&p2));

wyswietl(p2.odleglosc(&p1));

wyswietl(punkt::liczba_punktów()); // 2 obiekty

/*przekazywanie przez wartość - W metodzie odleglosc zostanie wywołany niejawny konstruktor kopiujący do utworzenia obiektu automatycznego na stosie, kopiujący niestatyczne pola przekazywanego obiektu p1 lub p2, bez inkrementacji pola ile_punktow. */

wyswietl(p2.odleglosc(p1, 2));

wyswietl(p1.odleglosc(p2, 2));

wyswietl(punkt::liczba_punktów()); //0 obiektów

}

wyswietl(punkt::liczba_punktów()); // -2 obiektów

} ... //pozostałe definicje w p.7 wykład 1

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 25

(6)

#ifndef PUNKT //plik nagłówkowy

#define PUNKT class punkt {

static int ile_punktow;

float x, y;

public:

... //pozostałe deklaracje w klasie w punkt jak w p.1 wykład 2

float odleglosc(punkt&); //deklaracje przeciążonych metod z parametrami obiektowymi

float odleglosc(punkt*);

float odleglosc(punkt, int);

};

#endif

#include "punkt2_2.h" //plik modułowy

#include <iostream.h>

#include <math.h>

... //pozostałe definicje metod jak w p.1 wykład 2

float punkt::odleglosc(punkt& p) //przekazywanie przez referencję

/*Na stos zostanie przekazany niejawnie adres aktualnego obiektu p. Wszystkie operacje są wykonywane na obiekcie aktualnym*/

{ return sqrt(pow(x - p.x, 2) + pow(y - p.y, 2));}

float punkt::odleglosc(punkt* p) //przekazywanie przez wskaźnik

/*Na stos zostanie przekazany jawny adres obiektu aktualnego podstawionego pod p. Wyłuskanie składowych obiektu następuje za pomocą operatora wyboru p® lub (*p).

Wszystkie operacje są wykonywane na parametrze aktualnym.*/

{ return sqrt(pow(x - p->x, 2) + pow(y - p->y, 2));}

float punkt::odleglosc(punkt p, int) //przekazywanie przez wartość

/*Zostanie wywołany niejawny konstruktor kopiujący podczas tworzenia obiektu automatycznego na stosie, kopiujący niestatyczne pola przekazywanego obiektu p, bez inkrementacji pola ile_punktow.

Wszystkie operacje są wykonywane na obiekcie automatycznym. W jawnym konstruktorze można odwoływać się do pola statycznego. */

{ return sqrt(pow(x - p.x, 2) + pow(y - p.y, 2));

/*tutaj zostanie wywołany destruktor jawny, zmniejszający o 1 liczbę obiektów pamiętanych w globalnym polu statycznym klasy punkt*/ }

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 26

(7)

3. Przeciążanie konstruktora - konstruktor bezparametrowy i z parametrami

· W przypadku braku jawnie zdefiniowanego konstruktora kompilator zawsze dołączy niejawny konstruktor bezparametrowy. W przypadku jawnego zdefiniowanego dowolnego konstruktora kompilator nie dołączy własnej definicji konstruktora bezparametrowego.

· Inicjowanie obiektów z dostarczanymi z zewnątrz wartościami lub bezparametrowo z wartościami z góry ustalonymi dla danej klasy można rozwiązać przez przeciążanie konstruktora lub przez zastosowanie parametrów domniemanych

#include <iostream.h>

#include "punkt2_3.h"

... //pozostałe deklaracje w p.2 wykład 2

void main()

{ { punkt p1(1, 2), p2(2, 3); //wywołanie 2 razy konstruktora z parametrami

wyswietl(p1); // x = 1, y =2 wyswietl(p2); } // x = 2, y =3

{ punkt p1, p2; //wywołanie 2 razy konstruktora bez parametrów

wyswietl(p1); // x = 0, y =0

wyswietl(p2); } // x = 0, y =0

... //pozostałe definicje w p.2 wykład 2

#ifndef PUNKT //plik nagłówkowy

#define PUNKT class punkt

{ static int ile_punktow;

float x, y;

public: punkt (); //konstruktor bez parametrów punkt (float, float); //konstruktor z parametrami

... //deklaracje metod takie jak w p.2 wykład 2

}; #endif

#include "punkt2_3.h" //plik modułowy

#include <iostream.h>

#include <math.h>

... //pozostałe definicje w p.2 wykład 2

punkt::punkt(float xx, float yy)

{ cout<<"Konstruktor z parametrami\n"; x = xx; y = yy; ile_punktow+

+; }

punkt::punkt()

{ cout<<"Konstruktor bez parametrow\n"; x = 0; y = 0; ile_punktow+

+; }

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 27

(8)

4. Konstruktor z parametrami domniemanymi

Konstruktor z parametrami domniemanymi może zastąpić dwa konstruktory:

jeden z parametrami, drugi bez parametrów przypisujący w ciele funkcji domniemane wartości pól.

#include <iostream.h>

#include "punkt2_4.h"

... //deklaracje jak w p. 2 wykład2

void main()

{ { // wywołanie konstruktora x2 z jawnie podanymi parametrami punkt p1(1, 2), p2(2, 3);

wyswietl(p1); // x = 1, y =2

wyswietl(p2); } // x = 2, y =3

{ //wywołanie konstruktora x2 z domniemanymi wartościami parametrów

// równymi 0

punkt p1, p2;

wyswietl(p1); // x = 0, y =0

wyswietl(p2); } // x = 0, y =0

}

... //definicje jak w p. 2 wykład2

#ifndef PUNKT.H //plik nagłówkowy

#define PUNKT.H class punkt

{ static int ile_punktow;

float x, y;

public:

//deklaracja konstruktora z parametrami domniemanymi

punkt (float = 0.0, float = 0.0);

... //pozostałe deklaracje i wszystkie definicje jak w p.2 wykład 2

#endif

Uwaga: Definicja konstruktora z parametrami domniemanymi o wartości nadanej podczas deklaracji jest identyczna jak konstruktora z parametrami, podaną w p.2 wykład 2.

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 28

(9)

5. Zwracanie wyniku działania funkcji przez obiekt.

Autoreferencja - wskaźnik this.

Przekazywanie wyniku obiektowego działania funkcji przez:

· referencję do obiektu nielokalnego, przekazanego do funkcji

· wskaźnik do obiektu nielokalnego, przekazanego do funkcji

· wartość - przekazywany jest obiekt utworzony przez konstruktor kopiowania domyślny lub jawnie zadeklarowany i zdefiniowany w postaci Klasa(Klasa&).

Uwagi:

· Funkcja zwracająca wynik działania jako obiekt należący do jej własnej klasy udostępnia prywatne lub zabezpieczone składowe.

· Konstruktory i destruktory nie zwracają wyniku, stąd w deklaracji i definicji na należy stosować wskazania zwracanego typu.

· Wskaźnik this jest przekazywany niejawnie do każdej funkcji składowej za wyjątkiem składowych statycznych. Jest to adres obiektu wywołującego daną metodę.

#include <iostream.h>

#include "punkt2_5.h"

... //deklaracje jak w p. 4 wyklad2

void main()

{ {wyswietl(punkt::liczba_punktów()); //0 punktów

punkt p1(2, 3), p2(1, 2); //2 obiekty

punkt &p3 = p1.skrajny(p2);//p3 może być obiektem referencyjnym z obiektem p1 lub p2

wyswietl(punkt::liczba_punktów()); //2 obiekty

punkt* p4 = p1.skrajny(&p2); //p4 może być wskaźnikiem do obiektu p1 lub p2

wyswietl(punkt::liczba_punktów()); //2 obiekty

punkt p5 = p1.skrajny(p2, 1); //p5 może być kopią obiektu p1 lub p2

/*1. Domyślny konstruktor kopiujący przekazuje p2 do metody skrajny - 3 obiekty 2.Domyślny konstruktor kopiujący przekazuje wynik funkcji przez wartość-4 obiekty 3.destruktor usuwający punkt przekazany przez wartość do metody skrajny*/

wyswietl(punkt::liczba_punktów()); //1 obiekt (a są trzy obiekty - p.

7 )

} //tutaj koniec bloku i zostają usunięte wszystkie obiekty powołane w poprzednim bloku

// czyli 3 razy wywołano destruktor

{ wyswietl(punkt::liczba_punktów()); // -2 obiekty (a jest 0 obiektów) punkt p1, p2;

wyswietl(punkt::liczba_punktów()); // 0 ( a są 2 obiekty)

} // tutaj koniec bloku i zostają usunięte wszystkie obiekty powołane w poprzednim bloku

// czyli 2 razy wywołano destruktor Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 29

(10)

wyswietl(punkt::liczba_punktów()); // -2 (a jest 0 obiektów ) }... //definicje jak w p. 4 wyklad2

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 210

(11)

#ifndef PUNKT.H //plik nagłówkowy punkt2_5.h

#define PUNKT.H class punkt

{ static int ile_punktow;

float x,y;

public: punkt (float = 0.0, float = 0.0);

~punkt();

void przesun (float, float);

float odleglosc(punkt*);

punkt skrajny(punkt, int); //przez wartość parametr i wynik funkcji

punkt& skrajny(punkt&); //przez referencję parametr i wynik funkcji

punkt* skrajny(punkt*); //przez wskaźnik parametr i wynik funkcji

static int liczba_punktow();

float odcieta();

float rzedna(); };

#endif

#include "punkt2_5.h" //plik modułowy

#include <iostream.h>

... //reszta metod jak w p. 4 wykład 2

//p przekazywany przez wartość i wynik funkcji zwracany przez wartość punkt punkt::skrajny(punkt p, int)

{ /*powstaje obiekt automatyczny jako kopia p za pomocą konstruktora kopiowania*/

if (x >= p.odcieta() || y >=p.rzedna()) return *this;

/*powstaje obiekt za pomocą konstruktora kopiowania zawierający kopię obiektu wywołującego metodę.

Autoreferencja- wskaznik this jest przekazywany przez listę parametrów każdej metody oprócz statycznej*/

return p; //lub tutaj powstaje kopia obiektu p za pomocą konstruktora kopiowania // tutaj usuwany jest obiekt automatyczny i wywołany jest jawny destruktor

}

//p przekazywany przez referencje oraz wynik funkcji zwracany przez referencję punkt& punkt::skrajny(punkt& p)

{ if (x >= p.odcieta() || y >=p.rzedna()) return *this;

return p; }

//p przekazywany przez wskaźnik oraz wynik funkcji zwracany przez wskaźnik punkt* punkt::skrajny(punkt* p)

{ if (x >= p->odcieta() || y >=p->rzedna()) return this;

return p; }

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 211

(12)

6. Jawny konstruktor kopiowania

Jawny konstruktor kopiowania o postaci Klasa(Klasa&) powinien kopiować do utworzonego obiektu wszystkie pola obiektu przesłanego przez referencję w liście parametrów oraz może wykonywać inne operacje np. aktualizację liczby obiektów przechowywaną w polu statycznym klasy.

Wywołanie konstruktora kopiującego:

· przy przekazywaniu przez wartość obiektów do funkcji/metody

· przy zwracaniu przez wartość wyniku działania funkcji/metody

· przy tworzeniu obiektu wraz z inicjowaniem zawartością innego obiektu należącego do tej samej klasy

#include <iostream.h>

#include "punkt2_6.h"

... // reszta programu jak w p. 5 wykład 2

void wyswietl(punkt *);

void main()

{ {wyswietl(punkt::liczba_punktów()); // 0 obiektów punkt p1(2, 2), p2(1, 5);

wyswietl(punkt::liczba_punktów()); // 2 obiekty

punkt p3 = p1.skrajny(p2, 0); //wynik metody i parametr przez wartość

/*1. Jawny konstruktor kopiujący do przekazania p2 do metody skrajny

2. Jawny konstruktor kopiujący do przekazania wyniku funkcji przez wartość 3. Destruktor usuwający punkt przekazany przez wartość do metody skrajny*/

wyswietl(punkt::liczba_punktów);

// 3 obiekty wyswietl(&p1.suma(p2));

/*1.Jawny konstruktor zwykły dla punktu automatycznego w metodzie suma 2. Jawny konstruktor kopiujący do przekazania przez wartość wyniku funkcji 3.Destruktor usuwający punkt automatyczny przy wyjściu z metody

4.Dstruktor usuwający punkt przekazany przez wartość jako wynik funkcji suma do niezależnej funkcji wyswietl przez wskaźnik */

wyswietl(punkt::liczba_punktów()); // 3 obiekty

punkt p4 = p2; //konstruktor kopiujący tworzy p4 na podstawie p2

wyswietl(punkt::liczba_punktów()); // 4 obiekty

} // tutaj koniec bloku i zostają usunięte wszystkie obiekty powołane w poprzednim bloku // czyli wywołany będzie 4 razy destruktor

{ wyswietl(punkt::liczba_punktów()); // 0 obiektów punkt p1, p2;

wyswietl(punkt::liczba_punktów()); // 2 obiekty

} // tutaj koniec bloku i zostają usunięte wszystkie obiekty powołane w poprzednim bloku // czyli wywołany będzie 2 razy destruktor

wyswietl(punkt::liczba_punktów()); } // 0 obiektów

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 212

(13)

#ifndef PUNKT.H //plik nagłówkowy punkt2_6.h

#define PUNKT.H class punkt

{

static int ile_punktow;

float x,y;

public: punkt (float = 0.0, float = 0.0);

punkt(punkt&); // jawny konstruktor kopiowania

// użyty w metodach podanych poniżej punkt suma(punkt&); //przez wartość wynik metody

punkt skrajny(punkt, int); //przez wartość parametr i wynik metody

static int info();

void odcieta (float);

void rzedna(float yy) { y = yy;}; //metoda inline - dobre rozwiązanie

... //reszta deklaracji jak w p.5 wykład 2

};

#endif

#include "punkt2_6.h" //plik modułowy

#include <iostream.h>

#include <math.h>

punkt::punkt(float xx, float yy) {

cout<<"Konstruktor zwykly\n";

x = xx; y = yy; ile_punktow++;

}

punkt::punkt(punkt& p) {

cout << "Konstruktor kopiujacy\n";

x = p.odcieta(); y = p.rzedna(); ile_punktow++;

}

punkt punkt::suma(punkt& p) {

punkt pom(x + p.odcieta(),y + p.rzedna());

return pom;

}

void punkt::odcieta(float xx)

{ x = xx; } //taką definicja można jako inline umieścić w bloku deklaracji klasy

... //reszta definicji jak w p.5 wykład 2

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 213

(14)

7. Inicjowanie obiektów

Przekazywanie parametrów funkcji oraz zwracanie wyniku funkcji z zastosowaniem referencji i wskaźników nie wymaga tworzenia obiektów - muszą jednak istnieć obiekty powiązane referencją lub wskaźnikiem, gdyż bezpośrednio są związane z wynikiem i parametrami funkcji (p. 7.2 - miejsca w przykładowym programie 0, 1, 2, 3, 4, oraz wywołanie wyswietl(punkt&) ).

Przekazywanie przez wartość parametrów i wyniku działania funkcji jest bezpieczne - tworzone są obiekty z wywołaniem konstruktora kopiującego (p. 7.2 - miejsca w programie: 5, 6, 7, 9, 10) zawierające kopie obiektów automatycznych lub statycznych istniejące tak długo, jak będą „potrzebne”

(usuwane z wywołaniem destruktora).

Obiekty tymczasowe są takimi obiektami automatycznymi, które powstają, jeżeli wewnątrz wyrażenia zostanie jawnie wywołany konstruktor zwykły (p. 7.1 - miejsce w programie 1; p. 7.2 - miejsca w programie: 1, 2, 3, 4, 8, 11) i usuwane z wywołaniem destruktora, wtedy gdy jest już niepotrzebny.

Ogólne zasady tworzenia obiektów i inicjowania obiektów:

· obiekt = klasa() (konstruktor zwykły - tworzony jest obiekt tymczasowy, który jest usuwany z wywołaniem destruktora po przekazaniu danych do obiektu po lewej stronie)

· klasa obiekt (..), klasa obiekt, klasa obiekt = klasa() (konstruktor zwykły- tworzony jest obiekt automatyczny lub statyczny)

· klasa obiekt2 = obiekt1 (konstruktor kopiujący - tworzony jest obiekt2 statyczny lub automatyczny zawierający kopie danych z obiekt1)

· klasa obiekt1 = funkcja zwracająca obiekt przez wartość (konstruktor kopiujący - tworzony jest statyczny lub automatyczny obiekt obiekt1 )

· obiekt = funkcja zwracająca obiekt przez wartość (konstruktor kopiujący - tworzony jest obiekt po prawej stronie i następnie usuwany z wywołaniem destruktora tego obiektu po przekazaniu danych do obiektu po lewej stronie)

· obiekt automatyczny-parametr - tworzona jest kopia obiektu przekazanego przez wartość jako parametr funkcji/metody (konstruktor kopiujący)

· obiekt automatyczny-wynik - tworzona jest kopia obiektu przekazanego przez wartość jako wynik działania funkcji/metody (konstruktor kopiujący).

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 214

(15)

7.1. Tworzenie obiektów z inicjalizatorem

#include <iostream.h>

#include "punkt2_6.h"

... //reszta programu jak w p. 6 wykład 2

void main()

{ { // 0 obiektów

punkt p1(2, 2), p2(1, 5); //konstruktor zwykły tworzy p1 i p2 z jawnymi parametrami

// 2 obiekty

punkt p3; /*konstruktor zwykły z domniemanymi parametrami (konstruktor

bezparametrowy) tworzy p3*/

// 3 obiekty

punkt p4 = 3; //konstruktor zwykły tworzy punkt p4 z parametrami 3 i 0 // 4 obiekty

punkt p5 = p4; //konstruktor kopiujący tworzy p5 na podstawie p4

// 5 obiektów

punkt p6 = punkt(8, 9); //konstruktor zwykły z parametrami jawnymi tworzy obiekt p6;

//równoważne punkt p6(8, 9)

/*tworzony jest obiekt tymczasowy za pomocą konstruktora zwykłego z parametrami i przekazany do p6, następnie obiekt tymczasowy jest usuwany za pomocą destruktora*/

p6 = punkt(3, 6); // 1 - 6 obiektów }

} ... // 0 obiektów

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 215

(16)

7.2. Tworzenie obiektów związane z wywoływaniem funkcji / metod Zastosowanie funkcji z lewej strony operatora przypisania zwracającej obiektowy wynik działania przez referencje, wskaźnik i wartość (metoda skrajny).

#include <iostream.h>

#include "punkt2_6.h"

... //reszta programu jak w p. 6 wykład 2

void wyswietl(punkt&);

void wyswietl(int);

void main()

{ { punkt p1(2, 2), p2(1, 5);

wyswietl(p1); wyswietl(p2);

//zwracanie obiektowego wyniku metody przez referencje

punkt& p3 = p1.skrajny(p2); //0 //wynik metody i parametr przez referencje

wyswietl(p3); //obiekt p3 jest referencyjny dla obiektu p1

//funkcja zwracająca wynik przez referencje z lewej strony operatora przypisania

/* najpierw jest wywołana metoda skrajny zwracająca referencje do obiektu p1; następnie tworzony jest obiekt tymczasowy o składowych x=8, y=8 z wywołaniem konstruktora zwykłego, przypisanie do p1 i usunięcie obiektu tymczasowego z wywołaniem destruktora*/

p1.skrajny(p2) = punkt(8, 8); //1

wyswietl(p1); //p1.x=8,

p1.y=8

/*najpierw jest wywołana metoda skrajny zwracająca referencje do obiektu p1; następnie tworzony jest obiekt tymczasowy o składowych x=2, y=6 z wywołaniem konstruktora zwykłego, przypisanie do p1 i usunięcie obiektu tymczasowego z wywołaniem destruktora*/

p2.skrajny(p1) = punkt(2, 6); //2

wyswietl(p1); //p1.x=2,

p1.y=6

//zwracanie obiektowego wyniku metody przez wskaźnik

punkt* p4 = p1.skrajny(&p2); //wynik metody i parametr przez wskaźnik

wyswietl(*p4); //wskaźnik p4 zawiera adres obiektu p1 (2, 6)

//funkcja zwracająca wynik przez wskaźnik z lewej strony operatora przypisania

/*metoda skrajny zwraca wskaźnik do obiektu p1; następnie jest tworzony obiekt tymczasowy o składowych x=8, y=8 z wywołaniem konstruktora zwykłego, przypisanie do p1 i usunięcie obiektu tymczasowego z wywołaniem destruktora*/

*p1.skrajny(&p2) = punkt(8, 8); //3

wyswietl(p1); //p1.x=8, p1.y=8

/*metoda skrajny zwraca wskaźnik do obiektu p1; następnie jest tworzony obiekt tymczasowy o składowych x=3, y=7 z wywołaniem konstruktora zwykłego, przypisanie do p1 i usunięcie obiektu Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 216

(17)

tymczasowego z wywołaniem destruktora*/

*p2.skrajny(&p1) = punkt(3, 7); //4

wyswietl(p1); //p1.x=3, p1.y=7

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 217

(18)

//zwracanie obiektowego wyniku funkcji przez wartość

punkt p5 = p1.skrajny(p2, 0); // 5 //wynik metody i parametr przez wartość

/*1.konstruktor kopiujący do przekazania p2 do metody skrajny 2.konstruktor kopiujący do przekazania wyniku funkcji przez wartość(p1)

3.destruktor usuwający punkt przekazany przez wartość do metody skrajny*/

wyswietl(p5);

// 3 obiekty

//funkcja zwracająca wynik przez wartość z lewej strony operatora przypisania

/* najpierw jest wywołana metoda skrajny przekazująca przez wartość obiekt p2 (utworzenie obiektu automatycznego z wywołaniem konstruktora kopiującego-kopia p2) i zwracająca przez wartość wynik działania (utworzenie obiektu automatycznego z wywołaniem konstruktora kopiującego zawierającego kopie danych obiektu p1 ze względu na wynik działania metody skrajny); następnie tworzony jest obiekt tymczasowy o składowych x=8, y=8 z wywołaniem konstruktora zwykłego, przypisanie do kopii obiektu p1, wyświetlenie wyniku przypisania i usuniecie obiektu tymczasowego z wywołaniem destruktora; na końcu usuwana jest kopia obiektu p1*/

wyswietl(p1.skrajny(p2, 0) = punkt(8, 8)); // 6, 7, 8

wyswietl(p1); //p1.x=3, p1.y=7

/* najpierw jest wywołana metoda skrajny przekazująca przez wartość obiekt p1 (utworzenie obiektu automatycznego z wywołaniem konstruktora kopiującego-kopia p1) i zwracająca przez wartość wynik działania (utworzenie obiektu automatycznego z wywołaniem konstruktora kopiującego zawierającego kopie danych obiektu p1 ze względu na wynik działania metody skrajny); następnie tworzony jest obiekt tymczasowy o składowych x=1, y=1 z wywołaniem konstruktora zwykłego, przypisanie do kopii obiektu p1, wyświetlenie wyniku przypisania i usuniecie obiektu tymczasowego z wywołaniem destruktora; na końcu usuwana jest kopia obiektu p1*/

wyswietl(p2.skrajny(p1, 0) = punkt(1,1)); // 9, 10, 11

wyswietl(p1); //p1.x=3,

p1.y=7

// 3 obiekty

} //tutaj koniec bloku i zostają usunięte wszystkie obiekty powołane w poprzednim bloku

// 0 obiektów }...

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 218

(19)

8. Tworzenie obiektów posiadających obiekty składowe

Przykład: Zadeklarowano klasę kolo do obsługi kół zawierającą składową obiektową punkt jako współrzędne środka koła oraz promień typu float.

Klasa kolo posiada:

* pole statyczne i metodę statyczną do zliczania liczby kół

* metodę statyczną info zwracającą numer klasy kolo

* metodę obliczającą odległość między środkami koła wywołującego metodę oraz przekazanego przez referencję, metodą odleglosc klasy punkt

* metody zwracające pola: - p_promien typu float oraz p_srodek typu punkt

* konstruktor zwykły z parametrami domniemanymi i listą inicjacyjną (wieloargumentowy) lub bez listy argumentów, liczący obiekty typu kolo

* bezargumentowy lub wieloargumentowy konstruktor kopiujący, liczący obiekty typu kolo

* destruktor aktualizujący między innymi liczbę obiektów typu kolo.

Inicjowanie obiektów zawierających składowe jest podobny do inicjowania obiektów bez składowych obiektowych (wykład 2/p. 7). Kolejność inicjowania obiektów składowych zależy kolejności ich deklaracji w klasie głównej. Do inicjowania obiektów stosuje się konstruktory wieloargumentowe lub bez listy argumentów: zwykłe lub kopiujące.

8.1. Konstruktory bezargumentowe (bez listy argumentów) W przypadku wywołania:

· konstruktora zwykłego kola pierwszy wykonywany jest konstruktor bezparametrowy punktu (wywołanie konstruktora bezparametrowego punktu jako przypadku wywołania konstruktora z parametrami domniemanymi) i następnie ustawiane są jawnie pola punktu za pomocą konstruktora zwykłego koła. Istnieje jednak ograniczenie ze strony hermetyzacji - obiekt składowy punkt nie udostępnia swoich pól danych klasie kolo, dlatego do inicjowania pól obiektu składowego typu punkt zdefiniowano metody przeciążone punkt::odcieta(float) i punkt::rzedna(float).

· konstruktora kopiującego koła zawsze pierwszy jest wykonany zwykły konstruktor bezparametrowy punktu, a potem jawnie kopiowana jest zawartość obiektu przypisywanego do kola, tworzonego za pomocą konstruktora kopiującego kola.

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 219

(20)

#ifndef KOLO.H

#define KOLO.H

#include "punkt2_6.h"

class kolo

{ static int ile_kol;

float promien;

punkt srodek;

public: kolo (float = 0.0, float = 0.0, float = 0.0);

kolo(kolo&);

~kolo();

float odleglosc(kolo&);

float pole();

static int liczba_kol();

static int info();

float p_promien();

punkt& p_srodek();};

#endif

#include "kolo2_8.h"//plik modułowy z konstruktorami bez listy argumentów

#include <iostream.h>

kolo::kolo(float xx, float yy, float rr)

{ srodek.odcieta(xx); srodek.rzedna(yy); promien = rr; } kolo::kolo(kolo& p)

{ cout<<"Konstruktor kopiujacy kola\n";

srodek = p.p_srodek(); promien = p.p_promien(); ile_kol++; } kolo::~kolo()

{ cout<<"Destruktor kola\n"; ile_kol--;}

float kolo::odleglosc(kolo& p) { return

srodek.odleglosc(&p.p_srodek());}

int kolo::ile_kol = 0;

int kolo::liczba_kol() { return ile_kol;}

int kolo::info() { return 1;}

float kolo::p_promien() { return promien;}

punkt& kolo::p_srodek() { return srodek;}

Uwaga: plik modułowy dla klasy punkt może być taki sam jak w p. 6

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 220

(21)

wykład 2

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 221

(22)

8.2. Konstruktory z listą argumentów - konstruktor wieloargumentowy Postać:

Klasa::Nagłówek_konstruktora : lista_inicjacyjna {ciało konstruktora}

Obiekty składowe mogą być zainicjowane za pomocą swoich konstruktorów umieszczonych na liście konstruktora klasy głównej w kolejności deklaracji w klasie, a na końcu konstruktor klasy głównej.

Destruktory wywoływane są w odwrotnej kolejności: najpierw klasy głównej, a potem składowych. W przypadku wywołania:

· zwykłego konstruktora koła: pierwszy wykonywany jest zwykły wieloargumentowy konstruktor punktu z parametrami (kolejność wykonania konstruktorów umieszczonych w liście wynika z kolejności deklaracji w klasie głównej), a następnie konstruktor kola.

· konstruktora kopiującego kola : po wywołaniu pierwszy wykonywany jest wieloargumentowy konstruktor kopiujący punktu (tworzony jest punkt) i potem konstruktor kopiujący kola (tworzone jest kolo). Na liście argumentów konstruktora kopiującego kola można umieścić również zwykły konstruktor klasy punkt.

· w liście inicjowane są również składowe nieobiektowe (składowa promien w liście klasy kolo oraz składowe x, y w klasie punkt).

#include "punkt2_6.h" //plik modułowy klasy punkt z konstruktorami // zawierającymi listę argumentów

...

punkt::punkt(float xx, float yy): x(xx), y(yy) // konstruktor zwykły { ile_punktow++; }

punkt::punkt(punkt& p): x(p.odcieta()), y(p.rzedna()) //konstruktor kopiujący { ile_punktow++; }

...

#include "kolo2_8.h" //plik modułowy klasy kolo z konstruktorami //zawierającymi listę argumentów

...

kolo::kolo(float xx,float yy, float rr) : promien(rr), srodek(xx, yy)

{ cout<<"Konstruktor zwykly kola\n"; ile_kol++; } //konstruktor zwykły

kolo::kolo(kolo& p) : srodek(p.p_srodek()), promien(p.p_promien())

{ cout<<"Konstruktor kopiujacy kola\n"; ile_kol++; } //konstruktor kopiujący ...

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 222

(23)

Program główny wykorzystujący konstruktory z p. 8.1 i 8.2

Uwaga - należy wykonać dwa programy tworząc dla podanych plików nagłówkowych po dwa różne pliki modułowe (jeden zawierający konstruktory bez listy argumentów i drugi z konstruktorami wieloargumentowymi),

#include <iostream.h>

#include "kolo2_8.h"

#include "punkt2_6.h"

void wyswietl(kolo&);

void wyswietl(punkt&);

void main()

{ {kolo p1(2, 2, 3), p2(1, 5, 6);

wyswietl(kolo::liczba_kol(), kolo::info()); // 2 koła i 2 punkty

wyswietl(punkt::liczba_punktow(), punkt::info());

wyswietl(p1); wyswietl(p2);

kolo p3; // p. 8.1-bezparametrowe konstruktory zwykłe punktu i koła

// p. 8.2-wieloargumentowe bezparametrowe konstruktory zwykłe punktu i koła

wyswietl(p3); // srodek.x=0, srodek.y=0. Promien=0

kolo p4 = 2; // p. 8.1-konstruktory zwykłe: punktu i koła

// p. 8.2-wieloargumentowe konstruktory zwykłe punktu i koła

wyswietl(p4); // srodek.x=2, srodek.y=0, Promien=0 // 4 koła i 4 punkty

kolo p5 = p1; // p.8.1-konstruktor bezparametrowy zwykły punktu i kopiujący koła // p. 8.2-wieloargumentowe konstruktory kopiujące punktu i koła

wyswietl(p5); //srodek.x=2, srodek.y=0. Promien=0 // 5 kół i 5 punktów

kolo p6 = kolo (5, 5, 5); // p. 8.1-konstruktory zwykłe punktu i koła º kolo p6 (5,5,5) // p. 8.2-wieloargumentowe konstruktory zwykłe punktu i koła

wyswietl(p6); // srodek.x=5, srodek.y=5. Promien=5 // 6 kół i 6 punktów

p4 = kolo (6, 6, 6); /* p. 8.1- obiekt kolo tymczasowy za pomocą zwykłych konstruktorów punktu i koła, przypisany do p4 i usunięty za pomocą destruktora*/

/* p. 8.2-obiekt kolo tymczasowy za pomocą wieloargumentowych zwykłych konstruktorów punktu i koła, przypisany do p4 i usunięty za pomocą destruktora kola i punkt*/

wyswietl(p4); // srodek.x=6, srodek.y=6. Promien=6 // 6 kół i 6 punktów

} //wykonanie 6 par destruktorów w kolejności: destruktor koła, i potem punktu

} // 0 kół i 0 punktów

void wyswietl(kolo& p)

{ wyswietl(p.p_srodek()); cout<<"Promien: "<< p.p_promien() << '\n';}

Zofia Kruczkiewicz, p.325 c3 Programowanie obiektowe w C++, Wykład 223

Cytaty

Powiązane dokumenty

[r]

Ponadto relacja jest przechodnia, ponieważ jeżeli pa, bqρpx, yq oraz px, yqρpz, wq, to z definicji ay “ bx oraz xw “ yz.. Mnożąc te równości stronami otrzymujemy ayxw “ bxyz

Etap projektowania: należy zmodyfikować diagramy sekwencji, wstawiając linie życia kolekcji wszędzie tam, gdzie zachodzi potrzeba wykonanie metody dla wielu obiektów, a

Do obsługi urządzenia nie należy dopuszczać osób, które nie zapoznały się z instrukcją.. Instrukcję należy zachować, ponieważ może być potrzebna

The class numbers KK modulo p 2 for all prime conductors of given type less than 10 9 , computed by means of the congruence (2), are given in the following table... If this value

Podczas tego ćwiczenia studenci będą mogli zapoznać się z takimi operacjami, jak: ważenie na wadze technicznej, przygotowywanie roztworów wodnych, zatężanie

Wzajemne wykluczanie (ang. Mutual exclusion condition ) – Każdy z zasobów jest albo wolny albo zajęty przez dokładnie jeden proces. Wait and hold condition) – Proces

Zbiór procesów jest w stanie zakleszczenia jeżeli każdy proces z tego zbioru czeka na zdarzenie które może być spowodowane tylko przez inny proces z tego