• Nie Znaleziono Wyników

Programowanie obiektowe w C++

N/A
N/A
Protected

Academic year: 2021

Share "Programowanie obiektowe w C++"

Copied!
19
0
0

Pełen tekst

(1)

Programowanie obiektowe

w C++

Wykład 03 Temat wiodący:

Konstruktory i deskruktory

Konstruktory

i Destruktory

(2)

Konstruktor

n

Konstruktor — co to?

n

jest metodą służącą do inicjowania obiektów danej klasy

n

jest przepisem na utworzenie obiektu danego typu

n

Konstruktor — czy jest potrzebny?

n

czy dane zawarte w obiekcie wymagają inicjalizacji?

Konstruktor — deklarowanie

n Deklaracja konstruktora dla klasy T:

T(args); lub T::T(args);

class point {

double x, y;

public:

// …

point(double, double); // nie zwraca nawet void

point(double); // można go przeciążać

point();

};

(3)

Konstruktor — nietypowa metoda

n

Nie wolno określać typu wartości zwracanej (nawet void).

n

Nie można wywołać konstruktora na rzecz już istniejącego obiektu.

n

Nie można pobrać adresu konstruktora.

n

Nie jest widoczny w zakresie klasy i nie ma nazwy (wg. opisu języka).

Wywoływanie

n Konstruktor bezargumentowy (domyślny):

point p1;

n Pozostałe:

point p3(10.0, 20.0); // 2 arg.

point p2(1.0); // 1 arg.

// point p1(); // tak wygląda deklaracja funkcji p1

point p2=1.0; // tak tylko dla k. 1 arg.

(4)

Wywoływanie

n

można jawnie określić konstruktor

point p3=point(10.0, 20.0);

point p2=point(1.0);

point p1=point();

albo:

point p3=point::point(10.0, 20.0);

point p3=point::point(1.0);

point p1=point::point();

Wywoływanie

n

obiekty anonimowe

point pu; // obiekt nieanonimowy pu pu = point (3);

// tymczasowy obiekt anonimowy, // usunięcie (zaraz po przypisaniu lub // później, „gdy będzie niepotrzebny”) point(20);

// tymczasowy anonimowy i bezużyteczny point * ppu;

ppu=&point();

// błąd trudny do wyśledzenia, składniowo poprawne

(5)

Definiowanie

class point {

double x, y;

public:

// …

point(double, double);

point(double);

point() {

x=y=0.0;

};

};

inline point::point(double d) {

x=y=d;

}

point::point(double x0, double y0) {

x=x0;

y=y0;

}

Lista inicjacyjna

n w definicji konstruktora (i tylko tu) można wykorzystać listę inicjacyjną

T() : składowa(inicjalizator) [, składowa(inicjalizator) …] { }

class point {

double x, y;

public:

// …

point():x(0.0), y(0.0) {};

};

(6)

Lista inicjacyjna

inline point::point(double d) :x(d), y(d)

{

// zrobione }

point::point(double x, double y)

:x(x), y(y) // to jest jednoznaczne !!!

{

// zrobione }

Lista inicjacyjna

n

tylko tak można inicjalizować pola będące referencjami i pola ustalone.

n

w liście inicjacyjnej oprócz niestatycznych

składowych klasy (zadeklarowanych w klasie, a nie odziedziczonych) można określić sposób wywołania konstruktorów bezpośrednich przodków i przodków wirtualnych.

n

kolejność na liście inicjacyjnej nie ma znaczenia,

wykonywanie w kolejności: klasy bazowe (wirtualne

i bezpośredni przodkowie w kolejności deklaracji),

składowe w kolejności deklaracji, ciało konstruktora.

(7)

Lista inicjacyjna

point::point(int x, int y):x(x), y(y) {}; //OK.

inline point::point(int i) :x(i), y(x) {}; //OK.

inline point::point(int i) :y(x), x(i) {}; //OK.

// point::point(int i) :y(i), x(y) {} — oops !!!

Konstruktor domyślny

n

jeżeli żaden konstruktor nie został zadeklarowany to kompilator dostarcza domyślny konstruktor

(bezargumentowy) o pustym ciele, dla klasy T:

T::T() { }

n

jeżeli my zadeklarujemy konstruktor (nawet tylko argumentowy) to kompilator nie dostarczy

domyślnego bezargumentowego.

(8)

Kolejność wywoływania konstruktorów

n

Konstruktory

n klasa (klasy) bazowa (bazowe w kolejności deklaracji)

n składowe klasy w kolejności deklaracji

n ciało konstruktora

n

Uwaga: obiektowe składowe klasy (oraz klasy bazowe), jeżeli nie zostaną zainicjalizowane w liście inicjacyjnej, to będą inicjalizowane 2 razy:

n konstruktorem bezargumentowym swojej klasy

n następnie kodem z ciała konstruktora tworzonego obiektu

Przykład

class segment {

point p1;

int number;

point p2;

};

segment::segment() // jak to zadziała???

:p1(1.0, 1.0) {

p2=point(1.0);

};

(9)

Przykład

class segment {

point p1;

int number;

point p2;

};

segment::segment()

:p1(1.0, 1.0) // konstr. p1 (2-arg), konstr. p2 (domyślny)

{ // number niezainicjalizowany

p2=point(1.0); // konstr. temp. (1 arg.), przypisanie

}; // destr. temp.

Konstruktor kopiujący

n

służy do inicjalizacji obiektów danej klasy innymi obiektami tej samej klasy, dla klasy T ma postać:

T::T(const T &);

n

parametr musi być referencją, a nie zmienną (bo powstawałyby obiekty tymczasowe, które też trzeba zainicjalizować, też konstruktorem kopiującym)

n

parametr powinien być const aby można było

wywołać konstruktor z argumentem const

(10)

Konstruktor kopiujący

n

np. k.k. dla klasy point:

point(const point & p) :x(p.x), y(p.y) {}

n

Konstruktorem kopiującym może być też inny

kostruktor który można wywołać w taki sposób, np.:

point(const point &, int=7);

Konstruktor kopiujący generowany automatycznie

n

K.k. jest generowany automatycznie przez kompilator, gdy nie programista go nie zdefiniuje (inne

konstruktory są nieistotne).

n

generowany automatycznie k.k. skopiuje obiekt pole po polu

(klasy bazowe oraz pola obiektowe ich konstruktorami kopiującymi – analogicznie jak dla listy inicjalizacyjnej będzie to działać też gdy klasa ma składowe ustalone (const))

np.: point(const point & p) :x(p.x), y(p.y) {}

(11)

Destruktor

n

Co to jest destruktor?

n

łatwo zgadnąć

n

Kiedy jest przydatny?

n

jeszcze łatwiej

Destruktor

n

Destruktor klasy T:

~T();

n

np.:

~point() // nie ma argumentów ani typu zwracanego {

cout << ”\njestem sobie point (x:”

<< x << „ y:” << y;

<<„) a zaraz mnie już nie będzie”;

}

(12)

Destruktor

n

przeciwnie do konstruktora jest widoczny w zakresie klasy

n

destruktor można wywołać jawnie

n

destruktor domyślny – generowany gdy nie zdefiniowano destruktora

n

ma ciało puste, ale …

Kolejność wywoływania konstruktorów i destruktorów

n

Konstruktory

n klasa (klasy) bazowa (bazowe w kolejności deklaracji)

n składowe klasy w kolejności deklaracji

n ciało konstruktora

n

Destruktory – po prostu odwrotnie

n ciało destruktora

n destruktory obiektów składowych (kolejność przeciwna do deklaracji w klasie)

n destruktor klasy (klas) bazowych (kolejność przeciwna do deklaracji w klasie)

(13)

Kolejność wywoływania konstruktorów i destruktorów

n

obiekty zdefiniowane w blokach (lokalne, automatyczne)

n konstruktory są wywoływane gdy sterowanie napotyka na definicję obiektu

n destruktory po opuszczeniu bloku w kolejności odwrotnej do konstruktorów

n

obiekty globalne (statyczne)

n konstruktory w kolejności definicji, przed wywołaniem funkcji main()

n destruktory w kolejności odwrotnej, po zakończeniu main().

Kolejność wywoływania konstruktorów i destruktorów

n

obiekty dynamiczne kontrolowane są przez programistę za pomocą new i delete.

n

przydział pamięci i wywołanie konstruktora w momencie zastosowania operatora new

n

destruktor i dealokacja po delete

(14)

Konstrukcja i destrukcja obiektów dynamicznych

point *pp0=new point;

point *pp1=new point(1.0);

point *pp2=new point(10.0, 20.0);

point *tablica=new point[10];

// tablica 10 punktow

// inicjalizowanych konstr. bezarg.

// w kolejności rosnących adresów

// przy new T[] wyłącznie konstruktor bezargumentowy

delete pp1;

delete pp2;

delete pp0;

delete [] tablica;

Przykład

point global=777;

int f(int) { segment o; }

void main() { point local;

point *p_local;

local=global;

local=point(10,20);

int a=f(1);

for (int i=0; i<2; i++) { point w_bloku=local;

}

p_local = new point(1.0);

point local2(10,20);

delete p_local;

p_local = new point();

}

(15)

Przykład

point global=777;

int f(int) { segment o; } k4, k5, d5, d4 k1

void main() {

point local; k2

point *p_local;

local=global;

local=point(10,20); k3, d3 int a=f(1);

for (int i=0; i<2; i++) {

point w_bloku=local; k6, i==1 k7

} d6, i==1 d7

p_local = new point(1.0); k8

point local2(10,20); k9

delete p_local; d8

p_local = new point(); k10

} d9, d2,

d1, ???10

Przykład

n zdefiniować klasę person opisującą osoby

class person {

int age; // wiek char *name, // imię *lastName; // nazwisko public:

person(const char *name, const char *lastName, const int age);

person(const person & o);

~person();

};

(16)

inline person::person(const char *name, const char *lastName, const int age) :age(age)

{

person::name=new char[strlen(name) + 1];

strcpy(person::name, name);

person::lastName=new char[strlen(lastName) + 1];

strcpy(person::lastName, lastName);

}

inline person::person(const person & o)

:age(o.age), name(new char[strlen(o.name) + 1]), lastName(new char[strlen(o.lastName) + 1]) {

strcpy(name, o.name);

strcpy(lastName, o.lastName);

}

Przykład

inline person::~person() {

delete name;

delete lastName;

}

Przykład

(17)

Przykład

n zdefiniować klasę queue reprezentującą kolejkę osób (FIFO)

class queue {

person **persons; // tablica wskaźników do osób w kolejce const capacity; // pojemność kolejki

int length; // aktualna długość kolejki public:

queue(int capacity);

~queue();

int insert(const person &o); // wstaw, 1-brak miejsca, 0-wstawiono int collect(person &o); // pobierz, 1-kolejka pusta, 0-pobrano };

queue::queue(int capacity) :capacity(capacity), length(0),

persons((person **) new (person*) [capacity]) { // rzutowanie dla bc31

}

queue::~queue() {

for (int i=0; i<length; i++)

delete persons[i]; // elementy delete [] persons; // tablica }

Przykład

(18)

int queue::insert(const person &o) {

if (length==capacity) return 1;

persons[length++]=new person(o); // tworzymy kopie argumentu metody return 0;

}

Przykład

int queue::collect(person &o) {

if (length==0) return 1;

o.~person(); // jeszcze nie wiemy

o=*persons[0]; // jak przeciążyć operator przypisania

length--;

for(int i=0; i<length; i++) persons[i]=persons[i+1];

return 0;

}

Przykład

(19)

int queue::collect(person &o) {

if (length==0) return 1;

o.~person(); // jeszcze nie wiemy

o=*persons[0]; // jak przeciążyć operator przypisania

length--;

for(int i=0; i<length; i++) persons[i]=persons[i+1];

return 0;

}

// wytęż wzrok i znajdź wyciek pamięci !!!

Przykład

Cytaty

Powiązane dokumenty

W równaniach reakcji, w których ustala się stan równowagi, brak „ ⇄” nie powoduje utraty punktów.. Elementy odpowiedzi umieszczone w nawiasach nie

n Dla obiektu, którego klasy nie można jednoznacznie określić na etapie kompilacji, odwołania do metody, bądź metod zadeklarowanych jako wirtualne będą się odbywały

Abstrahując od leczenia farmakologicznego, rewaskulary- zacji, która jest bardzo ważna u chorych na niewydolność serca, ponieważ większość z nich ma chorobę wieńcową i na

Zdjęcia wykonanej pracy przysyłają tylko uczniowie z którymi się skontaktuję (Czat Teams).Pozostali uczniowie przechowują prace do wglądu. Drodzy Uczniowie zdrowych i

(4 pkt) W klasie Stos zdeniuj metody dost¦pu, wstawiania oraz usuwania elementu stosu  pa- mi¦taj, »e do stosu dost¦p jest tylko z jednej strony.. (4 pkt) W klasie Stos

DODATKOWE - na dodatkowe punkty lub wy»sz¡ ocen¦ (zadania 1-3 musz¡ by¢ wykonane!) Do realizacji podobnego jak wy»ej zadania i budowy klas wyj¡tków wykorzystaj bibliotek¦

– Czy przez te lata zdarzyła się Pani Czy przez te lata zdarzyła się Pani Czy przez te lata zdarzyła się Pani Czy przez te lata zdarzyła się Pani Czy przez te lata zdarzyła

Wraz z industrializacją i wywołanymi przez nią zmianami demo- graficznymi ateizm staje się w XIX wieku dostępną opcją światopoglą- dową i zyskuje zwolenników na