• Nie Znaleziono Wyników

Programowanie obiektowe w C++

N/A
N/A
Protected

Academic year: 2021

Share "Programowanie obiektowe w C++"

Copied!
27
0
0

Pełen tekst

(1)

Programowanie obiektowe w C++

dr inż. Tadeusz Wilusz

Akademia Ekonomiczna w Krakowie 31-510 Kraków, ul. Rakowicka 27 Budynek Biblioteki Głównej pokój 429 tel.: 2935-264

e-mail: wiluszt@ae.krakow.pl

Programowanie obiektowe

w C++

Wykład 01 Temat wiodący:

Wprowadzenie. Różnice C / C++

(2)

Plan wykładu

n

Wprowadzenie

n

Rozszerzenia nieobiektowe

n

Paradygmat obiektowy, klasa

Wprowadzenie

(3)

C++ historia

n

C++ wywodzi się z C (oba nadal rozwijane)

n

C wywodzi się z BCPL (martwy)

n

nie było języka A

C++ — C z klasami

n

narzędzie abstrakcji danych

n

język programowania obiektowego

n

ulepszony C

(4)

Książki o C++

n

Grębosz J.: Symfonia C++,Kallimach, Kraków

n

Porębski W.: Język C++. Wprowadzenie do programowania,HELP, W-wa

n

Grębosz J.: Pasja C++,Kallimach, Kraków

n

Plauger P.J., Biblioteka standardowa C ++.

WNT, Warszawa

n

Stroustrup B.: Język C++, WNT, W-wa

n

Stroustrup B.: Projektowanie i rozwój języka C++. WNT, Warszawa

Rozszerzenia C / C++

Rozszerzenia nieobiektowe:

komentarze „do końca linii”

wygodniejsza biblioteka we/wy;

funkcje inline;

argumenty domniemane funkcji;

referencje (przezwiska);

nowe operatory new i delete;

możliwość przeciążania nazw funkcji;

Rozszerzenia obiektowe:

klasy pozwalające na definiowanie typów obiektów;

funkcje i dane składowe klas (enkapsulacja);

możliwość tworzenia nowych klas przez dziedziczenie własności klas bazowych;

•sterowanie ukrywaniem informacji zawartej wewnątrz klasy;

konstruktory i destruktory obiektów;

(5)

Nieobiektowe rozszerzenia C++

Komentarz

/* komentarz C, stosowany

również w C++, wielowierszowy */

// jednowierszowy komentarz C++

// od „//” do końca wiersza

(6)

Komentarz

Nadal można używać preprocesora do „wyłączania”

większych fragmentów kodu źródłowego

#if 0

/* komentarz C, stosowany

również w C++, wielowierszowy */

// jednowierszowy komentarz C++

#endif

Komentarz

/* do komentarzy wielowierszowych

używaj komentarza z C lub z C++ */

// lecz ich nie mieszaj !!!

void foo() // tutaj użyj komentarza z C++

{

return; // wygodniejszy i bezpieczniejszy

}

(7)

Standardowe wejście i wyjście

n Nadal możemy używać funkcji C z <stdio.h>

n Powinniśmy używać operatorów strumieniowych z C++

(biblioteka <iostream.h>)

#include <iostream.h>

int a,b,c,d;

cout << „input a and b \n” ; cin >> a;

cin >> b;

cout << „input c and d \n”

cin >> c >> d;

Standardowe wejście i wyjście

n Strumienie nie są tak podatne na błędy, jak funkcje z <stdio.h>

(vide scanf() )

n Strumienie

n cin - std. input

n cout - std. output

n cerr - std. error output

n Manipulowanie łańcuchami, określanie precyzji, kontrola stanu, etc. – równie funkcjonalne jak w <stdio.h>

n nie należy mieszać operatorów C++ <iostream.h> z funkcjami C z <stdio.h>

(8)

Deklaracja jest instrukcją

n deklaracja wewnątrz bloku jest instrukcją

n może być umieszczona po innych instrukcjach {

int i=12;

cout << „statement”;

int j=i;

for (int k=0; k<20; k++) j+=k;

}

Deklaracja wewnątrz „for”

int i = 42;

int a[10];

for (int i = 0; i < 10; i++) a[i] = i;

int j = i; // j = 42

(9)

Deklaracja wewnątrz „for”

for ( forinitstatement; condition; expression ) is equivalent to

{

forinitstatement while ( condition ) {

statement expression ; }

}

goto

n

ograniczenia w stosunku do C:

n

tylko wewnątrz bloku

n

skok nie może pominąć inicjalizacji

(10)

goto

a:

int foo() { b:

goto b;

int i=7;

c:

return i;

} d:

void foofoo() {

e:

return;

}

Typy

n

silna kontrola typów (w porównaniu do C) – aby umożliwić kontrolę błędów

n

automatyczna konwersja typów – gdy nie prowadzi do niejednoznaczności

n

gdy to tylko możliwe, konwersja bez utraty precyzji/informacji (nie gwarantowane dla wszystkich konwersji:

char/short/int/long/single/float/double/signed/u

(11)

Typy

n

gdy nie określono typu, przyjmuje się int unsigned u;

const a;

static i;

n

zaleca się jawne określanie typu int

Typ void *

n

nie ma automatycznej konwersji do innych typów wskaźnikowych

void *malloc(size_t size);

char *str;

int *pi;

str = (char *) malloc(10);

pi = (int *)malloc(100);

(12)

Typ void *

n

nie ma automatycznej konwersji do innych typów wskaźnikowych

void free(void *block);

free(str);

free(pi);

const

n

nazwane stałe mają zastąpić definiowane stałe z C const five = 5;

void fooj(const int ci);

n

const – prawdziwe zmienne, z rozmiarem, adresem, operatorami, ale nie wolno ich modyfikować

n

ochrona przed błędami programisty

umożliwienie optymalizacji przez kompilator

(13)

const a wskaźniki

n

wskaźnik na stałą: const char *pc=”asdf”

(lub: char const *pc=”asdf”)

n

stały wskaźnik: char * const cp=”asdcf”;

n

stały wskaźnik na stałą :

const char * const cpc=”asdcf”;

błędy: pc[1]=‘2’; cp++; cpc[1]=‘b’; cpc--;

n

wskaźnikowi na stałą można przypisać adres zmiennej, odwrotnie nie

enum

enum numbers {ZERO, ONE, FIVE=5, SIX};

n

„numbers” to opcjonalna nazwa nowego typu

n

konwersja automatyczna z enum na int

n

dlaczego enum nie jest popularne?

(14)

Referencje

referencja (reference) do typu T: T&

n

wskaźnik, który wygląda jak zmienna int i=7, // zmienna

int & iref=i; // referencja – musi być zainicjalizowana // tj. skojarzona ze zmienną (i)

iref++; // teraz i==8

Referencje

void swap(int &i1, int &i2);

int a=2, b=3;

swap(a,b);

void swap(int &i1, int &i2) {

int i3;

i3=i1;

i1=i2;

i2=i3;

i1 i2 i3 a b

- - - 2 3

- - - 3 2

2 3 - 2 3

2 3 ? 2 3

2 3 2 2 3

3 3 2 3 3

3 2 2 3 2

(15)

Referencje – problemy

n problem: gdy parametr aktualny jest innego typu niż formalny, lub jest wyrażeniem

char c;

swap(a+20, c);

argumenty będą konwertowane do to const (const int), kompilator oczekuje int (nie const), powinien wygenerować błąd, zazwyczaj wygeneruje tylko ostrzerzeni.

wywołanie swap() nie odniesie skutku

Referencje – problemy

// int &ir=7; ERROR! 7 to stała

const int &ir1=7, // OK

&ir2=i+f; // OK

/* ir1 i ir2 – referencje do stałych obiektów

tymczasowych, żyjących tak długo jak ir1 i ir2

*/

(16)

Referencje – przykład użyteczny

int & min(int &i1, int &i2) {

return i1<i2 ? i1 : i2;

}

int a=10, b=20, c;

c=min(a,b);

min(a,b)++; //a==11 !

Referencje

n

mogą wprowadzać w błąd

n

unikaj funkcji modyfikującej swoje argumenty

n

używaj referencji, gdy ich rzeczywiście potrzebujesz

n dla oszczędzania pamięci

n dla oszczędzania czasu

n do zwracania obiektów, które będą dalej przetwarzane

n

używaj stałych referencji (optymalizacja,

(17)

Funkcje – Prototypy

C++ wymaga prototypów funkcji!!!

(wartość zwracana, nazwa, argumenty)

n

#include „foo_prototypes.h”

n

void foo();

n

void foo() {};

Funkcje – inline

inline int sum(int a, int b) {

return a+b;

}

n

zastępstwo makrodefinicji

n

„inline” to tylko zalecenie dla kompilatora

n

automatyczne rozwijanie inline funkcji

n

funkcja rozwinięta inline nie ma adresu

(18)

Funkcje przeciążone (overloaded)

n

wiele funkcji o tej samej nazwie, OK. w C++

int f(int, int);

int f(int);

int f(long);

Funkcje przeciążone

n

Adres funkcji przeciążonej – kompilator wymaga przesłanek wyboru wariantu funkcji

int (*pd)(long); //OK pd=f;

void *pf;

// pf=f; // ERROR!

(19)

Funkcje przeciążone

n Parametry funkcji przeciążonej muszą się różnić,

n Typ zwracany nie służy do rozróżniania funkcji przeciążonych, jest istotny gdy funkcja jest wywoływana

int f(int, int); int f(int); int f(long); // OK // int f(int); double f(int); ERROR int ff(int); int ff(double); // OK.

// ff(1L) ERROR! niejednoznaczność // void *p=ff(1) ERROR! typ zwracany

Dopasowywanie funkcji przeciążonych

n nie więcej niż jedna konwersja każdego argumentu

n wybierany najniższy poziom z możliwym dopasowaniem, niejednoznaczność to błąd dopasowania

n ścisła zgodność; bez konwersji lub tylko: nazwa tablicy na wskaźnik, nazwa funkcji na wskaźnik, T na const T

n zgodność przy promocjach w zakresie typów całkowitych:

char na int, short na int, poprzednie dla typów bez znaku, float na double

n konwersje standardowe: int ? double, pochodna* na podstawowa*, unsigned int ? int

n konwersje zdef. przez użytkownika

n zgodność przy zastosowaniu wielokropka (…)

(20)

Dopasowywanie funkcji przeciążonych

int f(int);

double f(double) void f();

int i1=f(1); // OK

int i2=f(1.0); // OK, wywołanie double f(double), // konwersja wyniku int

//int i3=f(„Hi”); ERROR! nie ma konwersji // char * do int ani do double

Funkcje przeciążone

n wygodne rozszerzenie konwersji automatycznych i jawnych int cmp (double a, double b)

{

return a – b;

}

int cmp (char *a, char *b) {

return strcmp(a,b);

(21)

Funkcje przeciążone

n nadal korzystamy z konwersji automatycznych cmp (1, 2); //OK., konwersja do double przed

//wywołaniem cmp (double a, double b)

n można zoptymalizować kod

int cmp (int a, int b) // teraz cmp(1, 2) bez konwersji {

return a – b;

}

Domyślne argumenty funkcji

void line(int len, char c=‘*’) {

for (int i=0; i<len; i++) cout << c;

}

n teraz to: line(x);

znaczy: line(x, ‘*’);

n a to: line(x, ‘o’);

znaczy: line(x, ‘o’);

(22)

Domyślne argumenty funkcji

int fun(int i1, int i2=20, int i3=30);

n

po pierwszym domyślnym wszystkie następne muszą być domyślne

n

funkcja taka nie jest przeciążona,

&fun(int) == &fun(int, int)

n

możemy niezależnie stosować przeciążanie:

int fun(int i1, int i2);

//deklaracja nie jest niejednoznaczna, //ale wywołanie fun (int, int) jest!

Domyślne argumenty funkcji

n

uwaga na „type * =” — po „*” spacja

n

argumenty domyślne można zdefiniować tylko raz (formalnie albo w prototypie, albo w

definicji).

Argumenty domyślne definiuj w pliku

nagłówkowym!

(23)

Zmienna liczba argumentów funkcji

n w C pisaliśmy:

int printf(char *, …);

n w C++ jest prościej:

int printf(char * …);

// można pominąć przecinek przed …,

// ale tylko wtedy, gdy zmienna poprzedzająca „…”

// nie ma wartości domyślnej.

// ma <stdarg.h >

n w C++ jest prościej:

funkcje można przeciążać

Zarządzanie pamięcią

n przydział pamięci: operator new składnia: new Typ

int * pi = new int; // pi = (int*)malloc(sizeof(int))

n zwolnienie: operator delete składnia: delete pointer

delete pi; // operator delete nie zmienia wartości // swojego argumentu

(24)

Zarządzanie pamięcią

n zarządzanie wektorami (tablicami) int * pai = new int [x];

delete [] pai;

n programista sam decyduje, którą wersję operatora delete użyć (kompilator tego nie sprawdzi i nie ostrzeże)

n wielowymiarowe tablice:

int *pmai = new int[x][20][30]

// wszystkie wymiary, za wyjątkem pierwszego, // muszą być znane już podczas kompilacji delete [] pmai;

Zarządzanie pamięcią

n

można zadeklarować funkcję (new_handler), będzie wywołana gdy zabraknie pamięci

set_new_handler(); //<new.h>

n

gdy nie zdefiniowano new_handler, new zwraca 0 (NULL)

n

delete NULL; nie robi nic

n

nie mieszaj new/delete z malloc/free

(25)

Inne rozszerzenia

n

Szablony (Templates)

n

Wyjątki (Exceptions)

n

Namespace

Paradygmat programowania

obiektowego, klasa, obiekt

(26)

Paradygmat

paradygmat (słownik PWN) — przyjęty sposób widzenia rzeczywistości w danej dziedzinie

n

Paradygmaty programowania

n

programowanie strukturalne

n

programowanie obiektowe

Paradygmat programowania obiektowego

programowanie obiektowe — to paradygmat rozwiązywania problemów programistycznych

z wykorzystaniem obiektów, sposób interpretacji problemu jako zbioru obiektów i

relacji pomiędzy nimi.

(27)

Obiekt

n

Potoczne znaczenie słowa obiekt

n

Znaczenie pojęcia obiektu w programowaniu

n

Reprezentuje na potrzeby programu obiekty ze świata rzeczywistego lub abstrakcyjne (w potocznym znaczeniu słowa obiekt)

n

Uogólniona zmienna (struktura)

n

Zdefiniowany i używany zgodnie ze składnią i semantyką języka

Obiekt - uogólniona zmienna (struktura)

n

Struktura

n

zestaw danych, najczęściej różnych typów

n

Uogólniona

n

obiekt = dane + metody operujące na tych danych

Cytaty

Powiązane dokumenty

Jaką drogę przebędzie on do chwili zatrzymania się, jeśli współczynnik tarcia krążka o lód wynosi f=0,1?.

Należy udowodnić całkowitą poprawność tego pro- gramu względem

• Pami¦tajmy, dªugo±¢ stringu to jest ilo±¢ jego znaków, a rozmiar stringu (jako tablicy) jest zawsze o 1 wi¦kszy.... • Je»eli string inicjalizujemy od razu w momencie

(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

[r]

[r]

[r]

[r]