wyklad1 wprowadzenie klasy

background image

Programowanie obiektowe

Andrzej Walczak

awalczak@wat.edu.pl

WAT

Pierwsza edycja 2006

Temat: ogólny opis techniki obiektowej

background image

Uwagi wprowadzające

• Jest nowy syllabus przedmiotu.

Studenci powinni się z nim zapoznać.

• Literatura podstawowa:

wazniak.mimuw.edu.pl; Bruce Eckel –
Thinking in C++; Bruce Eckel –
Thinking in Java; Nicolai Josuttis – C+
+ Biblioteka Standardowa

background image

Ogólne cechy obiektowej techniki programowania

Zarządzanie informacją w programie –

współdzielenie danych

 

Większość wysiłku usprawniającego pisanie dużych
programów koncentrujemy na dzieleniu procedur (etapów
integralnych wykonania kodu) na moduły. Istnieje jednak
inny składnik programu nie mniej ważny niż kod napisany
w wybranym języku. Tym składnikiem są dane czyli
zestaw informacji, na których funkcjonują procedury
programu.

background image

Ogólne cechy obiektowej techniki programowania

Zarządzanie informacją w programie –

współdzielenie

danych

Jeśli program do swojego działania potrzebuje tylko kilka
kawałków danych, to bez utraty bezpieczeństwa te kawałki
mogą być udostępniane wszystkim podprogramom
tworzącym kod.
Taka organizacja danych jest wygodna dla programistów
ponieważ współdzielony zestaw danych jest czymś w
rodzaju tablicy ogłoszeniowej na której podprogramy mogą
wymieniać się informacjami. Jeśli jednak tych kawałków
danych i podprogramów są tysiące takie rozwiązanie często
prowadzi do nieprzewidywalnych zachowań programu.

background image

Ogólne cechy obiektowej techniki programowania

Zarządzanie informacją w programie –

współdzielenie danych

Problem polega na tym, że współdzielenie danych
jest

pogwałceniem

modułowej

konstrukcji

programowania, której podstawą jest całkowita
niezależność

modułów.

Dopuszczając

swobodne współdziałanie modułów poprzez
wymianę

informacji

powodujemy,

że

zachowanie jednego modułu wpływa na
zachowanie wszystkich pozostałych
.

background image

Ogólne cechy obiektowej techniki programowania

• Rozwiązaniem jest

podzielenie danych

na części odpowiadające

modułom programu.

Podprogramy otrzymują dane, którymi

tylko

one mogą się posługiwać

. Taki zabieg nazywa się przesłanianiem

danych.

Wiele programów musi korzystać z tych samych danych

wielokrotnie np. obliczenia inżynierskie, programy księgowe etc.

Często z programów tego rodzaju korzysta jednocześnie wiele

osób. Zawsze istnieje możliwość, że jedna z nich zmieni dane,

któreych inne osoby właśnie używają.

• Dlatego utworzono tak zwane systemy dostępowe rozbudowane

aktualnie do Systemów Zarządzania Bazami Danych (Data Base

Management System). Kierują one wielodostępem do danych i

chronią je przed zmianami.

Okazało się , że idea DBMS jest niezwykle skuteczna w tworzeniu

kodu o podniesionej niezawodności. Ma jednak ten mechanizm

szereg ograniczeń . Kłopoty ze współdzieleniem danych

doprowadziły do utworzenia tak zwanego programowania

obiektowego.

background image

Ogólne cechy obiektowej techniki programowania

• Pierwszy język obiektowy – Simula 67 – powstał już w latach

sześćdziesiątych ubiegłego stulecia. Jego twórcami byli Ole-Johan

Dahl i Kristen Nygaard z Norsk Regnesentral w Oslo. Podczas

swoich prac nad symulacją statków musieli dla każdego rodzaju

statku

uwzględniać

wiele

atrybutów.

Ponieważ

liczba

modelowanych rodzajów statków była duża, uwzględnienie

wszystkich możliwych zależności między atrybutami stało się

problematyczne. Pojawił się pomysł, aby pogrupować różne

rodzaje statków w klasy obiektów. Każda klasa obiektów sama

miała być odpowiedzialna za definiowanie swoich danych i

zachowania. Simula była pierwszym językiem programowania, w

którym wprowadzono pojęcie klasy i jej egzemplarza. Warto tu

zwrócić uwagę, że zgodnie z nazwą języka takie odwzorowanie

obiektów spotykanych w świecie rzeczywistym na obiekty

programowe można nazwać symulacją. Niedługo potem w

laboratorium badawczym Xerox's Palo Alto stworzono Smalltalk.

Jego głównym pomysłodawcą był Alan Kay. Smalltalk zawierał

wiele rewolucyjnych pomysłów - m.in. dziedziczenie - i zyskał

sobie sporą popularność. W pewnej skali był również z

powodzeniem stosowany w praktyce. Standardem przemysłowym

programowanie obiektowe stało się jednak dopiero w latach

dziewięćdziesiątych za sprawą języka C++, który jest obiektowym

rozszerzeniem C. Obecnie jednym z najpopularniejszych języków

obiektowych i równocześnie języków programowania w ogóle jest

Java. *

*wazniak.mimuw.pl

background image

Trzy (albo dwa) klucze do techniki obiektowej:

obiekty, klasy, komunikaty

 

Jedną z barier w zrozumieniu techniki obiektowej
jest specjalistyczne słownictwo, którym ta technika
obrosła.
W rzeczywistości można tym żargonem posługiwać
się skutecznie stosując zaledwie kilka pojęć:

1. obiekt, instancja (konkret)

,

2. metoda, (funkcja składowa klasy)
3. komunikat, [
pojęcie od dawna zaniedbane ]
4. klasa,
5. podklasa,

6. dziedziczenie,
7. hermetyzacja (enkapsulacja),
8. abstrahowanie,
9. polimorfizm

.

background image

O obiektach

Koncepcje programowania obiektowego zostały pokazane w języku
Simula. Zbudowano go do symulacji złożonych systemów i jako
podstawę konstrukcji języka przyjęto, że

każdy obiekt rzeczywisty

charakteryzują jego zachowania

.

Spróbowano więc tak układać komunikacje pomiędzy

procedurami i danymi aby były podporządkowane

zachowaniom symulowanych obiektów

.

Obiekt był „pakunkiem” zawierającym procedury i dane powiązane
razem tak, aby określały jego możliwe zachowania. Procedury w
podejściu obiektowym nazywa się metodami. W odniesieniu do
danych stosujemy nazwę zmienne bo ich wartość może się zmieniać
w czasie. Nazywamy metody i zmienne atrybutami obiektu.

background image

Rozważmy dla ilustracji jak moglibyśmy programować

przenośnik

fabryczny

. Może on wykonywać rozmaite czynności jak

przemieszczanie się, ładowanie, rozładowanie. Musi przechowywać
informacje
o nośności, rozmiarach palety, prędkości, aktualnego
położenia, aktualnego ładunku, itp.

Tak więc realny obiekt „coś robi”

i „coś wie”.

Czynności obiektu opiszemy jako metody, a wielkości
charakterystyczne, którymi obiekt się posługuje
wykonując czynności, jako zmienne.

CZYNNOŚCI OBIEKTU = METODY

DANE DO METOD=ZMIENNE OBIEKTU

Obiekt jest idealnym modułem programu. Tworzy własny,
zamknięty świat. Wszystko co „wie” wyrażają jego
zmienne. Wszystko co może robić wyrażają jego metody.

background image

Klasy obiektów

Wykład 2

background image

Pojęcie klasy obiektów

Klasa jest nowym typem zmiennej w programie . Definiujemy ją

jako:

 
class nasza_klasa {
//
//
...
//ciało klasy
};
 
Jeśli chcemy stworzyć konkretny element czyli obiekt tej klasy to

zapisujemy :

 
nasza_klasa

nasz_obiekt

;

 

Wtedy w pamięci operacyjnej

powstanie

obiekt klasy

nasza_klasa, który się nazywa nasz_obiekt.

background image

Kiedy już mamy typ nasza_klasa, to możemy utworzyć obiekt pochodny, na
przykład wskaźnik do obiektu z naszej_klasy:
 

nasza_klasa *wsk;

(czy mogę określić referencję na nazwę klasy?) 

albo:
 

nasza_klasa &name = obiekcik;

 

Utworzy to wskaźnik do obiektów klasy nasza_klasa albo referencje do
wybranego obiektu klasy nasza_klasa.
 
Przykład: program w C++, który przechowuje informację o kolorze i wartości
punktowej karty do gry. Wykorzystuje klasę Karta
. W kodzie ponumerowano
wiersze do dalszej analizy.

background image

Kod programu do przykładu

1. #include <iostream>
2. #include <conio.h>
3. #include <string.h>
4. #include <dos.h>
5. class Karta
6. {
7. public:
8. char kol[80];
9. int wym;
10. Karta(char*, int);
11. void Druk();
12. };

background image

void main()
{

Karta k1(“czarna”,5),k2(“czerwona”,8); //

powolanie do zycia

obiektow k1 oraz k2 klasy Karta

k1.Druk();

//

wykonanie funkcji Druk() na rzecz obiektu k1

k2.Druk();

strcpy(k1.kol,”czarno-czerwona”); //

zmiana zmiennej kol na rzecz

obiektu k1

k2.wym=28;

//

zmiana zmiennej wym na rzecz obiektu k2

cout<<endl;

k1.Druk();
k2.Druk();
getch();
}

background image

Karta::Karta(char* s,int w): wym(w)
{
strcpy(kol,s);
}

 

Definicja
konstruktora

Inicjalizacja
argumentu
konstruktora

Definicja
funkcji
składowej klasy

void Karta::Druk()
{
cout<<”\nkolor=”<<kol<<”,wymiar=”<<wym;
}

background image

omówienie:

uwagi o strukturze kodu programu:

• opis klasy Karta znajduje się przed blokiem main() czyli w tej części

kodu programu, która przeznaczona jest do umieszczania deklaracji,
definicji i inicjalizowania typów zmiennych. To także wskazuje, że

klasa jest typem zmiennej

.

• Opis klasy zawsze umieszczamy w nawiasie klamrowym, po którym

jest średnik, tak, jak w normalnych deklaracjach typów zmiennej.

• Konstruktor obiektu Karta, o ZAWSZE nazwie takiej samej jak klasa

jest w obszarze opisu klasy tylko deklarowany i podawana jest lista
jego argumentów. Nie podajemy typu pomimo, że jest funkcją.

• Ciało konstruktora, który jest funkcją, jest opisywane

poza

blokiem

main() jeśli konstruktor jest podany jawnie

• W bloku definiowania klasy deklarowane są także funkcje

składowe klasy, które dalej będą metodami obiektów klasy. W
przykładzie jest to funkcja Druk().

• Opis funkcji klasy umieszczamy po bloku main() tak, jak opis

konstruktora ale może być podany także wewnątrz bloku deklaracji
klasy.

background image

Opis kodu:

Wiersze 5-11: początek i koniec opisu klasy Karta zawierający
deklaracje konstruktora Karta i funkcji Druk() oraz wykorzystywanych
zmiennych, tablicy char[80] oraz zmiennej całkowitej wym.

class Karta

{

public:

char kol[80];

int wym;

Karta(char*, int);

void Druk();

};

background image

Wiersze 12-25: blok main(), w którym powołane są dwa obiekty klasy Karta o
nazwach k1 i k2 w wierszu 14ym. Obiekty mają argumenty takie, jakie
zadeklarowano w konstruktorze
, czyli zmienna typu char oraz zmienna
integer. WNIOSEK: deklaracja konstruktora musi zawierać to, co potem
jest potrzebne w funkcjonowaniu obiektów konstruowanych w klasie
.
W każdym obiekcie k1 oraz k2 wartości zmiennych deklarowanych są
zainicjowane poprzez podanie konkretnych wartości.

void main()
{

Karta
k1(“czarna”,5),k2(“czerwona”,8);

k1.Druk();
k2.Druk();
strcpy(k1.kol,”czarno-czerwona”);
k2.wym=28;
cout<<endl;

k1.Druk();
k2.Druk();
getch();}

background image

Wiersze 26-33: definicja konstruktora klasy. Najpierw nazwa Karta, a
potem operator :: czyli operator zakresu. Teraz już na liście
argumentów formalnych podane są nazwy argumentów s oraz w. Po
liście argumentów formalnych może ( ale nie musi) pojawić się
dwukropek i lista inicjalizująca wartości argumentów, czyli argumenty
początkowe. Następnie w nawiasie klamrowym, po którym nie ma
średnika umieszczamy ciało konstruktora. W ciele konstruktora, w
wierszu 27 mamy kopiowanie łańcucha nazwy koloru karty z s do kol.

Karta::Karta(char* s,int w): wym(w)
{

strcpy(kol,s);

}

background image

Wiersze 34-36: definicja funkcji własnej klasy Karta o nazwie Druk(). Jest ona
wykonywana w bloku main() na rzecz obiektów k1 oraz k2. To, że jest ona
funkcją własną klasy Karta wskazuje nazwa klasy rozpoczynająca definicję i
operator zakresu :: , który wskazuje, że funkcja działa w całym zakresie
ważności klasy. Funkcja Druk() wykonuje na ekranie wypisanie nazwy koloru
karty i jej wartości punktowej.

void Karta::Druk()
{
cout<<”\nkolor=”<<kol<<”,wymiar=”<<wym;
}

k1.Druk();
k2.Druk();

background image

Kolor obiektu k1 jest modyfikowany w wierszu 18 funkcją strcpy. W
składni wymienia się nazwę obiektu, a po kropce nazwę argumentu
zmienianego. W wierszu 19 modyfikowany jest argument wym obiektu
k2 poprzez zwykłą operację przypisania nowej wartości.

k1.Druk();
k2.Druk();
strcpy(k1.kol,”czarno-czerwona”);
k2.wym=28;

WNIOSEK:

Klasa a obiekt

Widać, że

klasa nie definiuje konkretnych

obiektów tylko ich typy

!!! Jest ona typem

obiektu jako abstrakcyjnej zmiennej, a nie
obiektem lub zbiorem obiektów

.

background image

Uwagi ogólne do konstruktorów:

1. Konstruktor

NIE MUSI

wystąpić w opisie klasy, czyli obiekty nie muszą być

wprowadzane konstruktorem.

2. Nazwa konstruktora może być przeładowana

, czyli stosowana

wielokrotnie w opisie klasy z różnymi listami argumentów. Wtedy
kompilator odróżnia konstruktory po listach argumentów, tak, jak w
przypadku przeładowanych nazw funkcji. Konstruktorów może wiec być
wiele.

3. Konstruktor

może być wywoływany ( a nie deklarowany!!) bez żadnych

argumentów

. Jest to tak zwany konstruktor domniemany. Czasem

nazywamy go domyślnym albo standardowym. Ze względu na istotę
przeładowania nazwy konstruktor domniemany czyli bezargumentowy
może wystąpić tylko raz. Jeśli nie deklarujemy w klasie żadnego
konstruktora, to kompilator sam ustanawia właśnie konstruktor
domniemany do obsługi obiektów w programie. Każdy konstruktor z
argumentami, którym nadamy wartości domyślne czyli niedefiniowalne
jest także konstruktorem domniemanym.

4. Co właściwie robi konstruktor? On INICJALIZUJE obiekty. Kompilator

automatycznie wywołuje konstruktor w miejscu tworzenia obiektu zanim
jeszcze obiekt podejmie jakiekolwiek działanie. Czyli po pierwszym
komunikacie staruje konstruktor. Nazwa konstruktora taka sama jak
nazwa klasy (pomysł Stroustrupa) pozwala na jednoznaczne powiązanie
konstruktora z typem zmiennej obiektowej (wykorzystano operator
zakresu).

background image

Konstruktor jest zwykle deklarowany jako
publiczny, bo przecież wprowadzane nim
obiekty mogą być używane przez klasy
zewnętrzne. Możemy jednak dla
konstruktora przewidzieć ochronę tak, jak
dla klas za pomocą etykiet private lub
protected. Wówczas jednak także
konstruowane obiekty będą dostępne tylko
w obrębie klasy z tym konstruktorem jako
private albo jako protected tylko w zakresie
klas dziedziczących.

Konstruktor może zamiast definiować
obiekty podawać kopie obiektów zawartych
w innej klasie lub tworzyc kopie obiektów
istniejących. Wtedy jest to tak zwany

konstruktor kopiujący

.

Konstruktor może dokonywać konwersji typu
obiekty z jednego w drugi. Nazywamy go
wtedy

konstruktorem konwertującym

.

background image

Przykład: Konstruktor domniemany

#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <dos.h>
class X
{
public:
char kol[80];
int wym;

X(char* s=“?”, int w=-1);

void Druk();
};

#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <dos.h>
class Karta
{
public:
char kol[80];
int wym;

Karta(char*, int);

void Druk();
};

background image

void main()
{
clsscr();

X k1,k2(“fiolet”);

k1.Druk();
k2.Druk();
strcpy(k1.kol,”biala”);
strcpy(k2.kol, k1.kol);
k1.wym+=10;
k2.wym=k1.wym*5;
cout<<endl;

k1.Druk();
k2.Druk();
cout<<”\n\n”<,”size=”<<si
zeof(k1);
cout<<”\n\n”<,”size=”<<si
zeof(X);
 
getch();
}

void main()
{
clsscr();

Karta
k1(“czarna”,5),k2(“czerwona”,8);

k1.Druk();
k2.Druk();
strcpy(k1.kol,”czarno-
czerwona”);
k2.wym=28;
cout<<endl;

k1.Druk();
k2.Druk();
getch();
}

background image

X::X(char* s,int w)
{
wym=w;
strcpy(kol,s);
}
void X::Druk()
{
cout<<”\nkolor=”<<kol<<”,w
ymiar=”<<wym;
}

Karta::Karta(char* s,int w):
wym(w)
{
strcpy(kol,s);
}
void Karta::Druk()
{
cout<<”\nkolor=”<<kol<<”,wym
iar=”<<wym;
}

background image

Cechy obiektów

• Poprzez sposób definiowania obiektu decydujemy o

zakresie ważności jego nazwy czyli także o czasie jego

życia.

• Jeśli obiekt jest definiowany w dostępie publicznym to

rozumiemy, że jest dostępny globalnie (uwaga na Grębosza

i pomyłkę pomiędzy pojęciem zmiennej typu wbudowanego

i obiektem) czyli mogą z niego korzystać wszystkie funkcje i

obiekty innych klas w programie.

• Obiekt może funkcjonować lokalnie (obiekt prywatny) i

wówczas automatycznie kończy się jego zakres ważności

wtedy, kiedy fragment programu (klasa, blok) pozostaje

zakończona faktycznie. Taki obiekt –podobnie jak zmienna

lokalna – traci swoje cechy (pomimo hermetyzacji) w

zakresie wartości jego zmiennych i metod. Taki obiekt,

podobnie jak zmienną lokalną, będziemy uważać za

zapisywany automatycznie.

background image

Cechy obiektów

• Obiekt globalny jest inicjalizowany inaczej niż lokalny bo

wstępnie (zanim zacznie funkcjonować jako konkret) jest
inicjowany zerami.

• Obiekt mogę powołać do życia jako obdarzony atrybutami.

W szczególności może to być atrybut static. Taki obiekt,
nawet jeśli jest lokalny, zachowa swoje wartości zmiennych
i metod takie, jak przy ostatnim komunikacie. Inicjalizacja
jest tu podobna jak obiektu globalnego – wartościami
zerowymi.

• Jeśli atrybutu static użyjemy do nazwy globalnej, to może

ona być dostępna TYLKO W SWOIM PLIKU. Oznacza to, że
nie mogę uzyskać dostępu do takiego obiektu wtedy, kiedy
jest on w pliku dołączonym dyrektywą preprocesora include
jako plik nagłówkowy.

background image

this - WSKAŹNIK SPECJALNY

• Każdej funkcji - metodzie zadeklarowanej wewnątrz klasy

zostaje

w momencie wywołania w niejawny sposób (ang. implicitly)

przekazany wskaźnik do obiektu (w stosunku do którego

funkcja ma

zadziałać). Pointer wskazuje funkcji w pamięci ten obiekt,

którego członkiem jest dana funkcja. Bez istnienia takiego

właśnie wskaźnika nie moglibyśmy stosować spokojnie

funkcji, nie

moglibyśmy odwoływać się do pola obiektu, gdybyśmy nie

wiedzieli

jednoznacznie, o który obiekt chodzi.

• Wskaźnik this jest pierwszym argumentem konstruktora

obiektu. W konstruktorze wskazuje on na nie

zainicjalizowany fragment pamięci, a rolą konstruktora jest

właśnie inicjalizacja na rzecz konkretnego obiektu

(konkretu).

background image

this - WSKAŹNIK SPECJALNY, c.d.

• Program posługuje się automatycznie niejawnym

wskaźnikiem do obiektu (ang. implicit pointer). Możemy

wykorzystać ten istniejący, choć do tej pory nie widoczny

dla nas pointer posługując się słowem kluczowym this (ten).

This pointer wskazuje na obiekt, do którego należy

funkcja. Korzystając z tego wskaźnika funkcja może bez

cienia

wątpliwości zidentyfikować właśnie ten obiekt, z którym

pracuje

a nie obiekt przypadkowy.

[!!!] FUNKCJE KATEGORII static NIE OTRZYMUJĄ POINTERA

this.

Należy pamiętać, że wskaźnik this istnieje wyłącznie

podczas

wykonywania metod (ang. class member function

execution), za

wyjątkiem funkcji statycznych.

background image

Tworzenie obiektów

Kiedy w C++ tworzony jest obiekt zachodzą dwa procesy:

1.

przydział pamięci do obiektu

2.

Wywołanie konstruktora inicjalizującego tę pamięć.

Pierwszy proces może być wykonany na różne sposoby i w różnym

czasie:

a.

Pamięć może zostać przydzielona, zanim zacznie się praca

programu –w obrębie obszaru danych statycznych. Obszar ten

istnieje przez cały czas działania programu.

b.

Pamięć może zostać przydzielona na stosie kiedy zostanie

osiągnięty określony punkt realizacji programu (klamrowy

nawias otwierający). Jest ona zwalniana po pojawieniu się

klamrowego nawiasu zamykającego. Tutaj potrzebna jest wiedza

o liczbie i rozmiarze wykorzystywanych zmiennych aby nie

przekroczyć rozmiaru stosu.

c.

Pamięć jest przydzielana na stercie. Jest to proces dynamiczny.

Jest on obsługiwany odpowiednia funkcją. Czyli przydziela ją i

zwalnia program (czytaj programista) [malloc(), free() w

<cstdlib>, new, delete w standardowej bibliotece poprzez

przestrzeń nazw]


Document Outline


Wyszukiwarka

Podobne podstrony:
wyklad1 wprowadzenie klasy
IOpr, wykład 1, wprowadzenie
Socjologia i psychologia cyklów życia Wykład wprowadzający
Inzynieria wyklad wprowadzajacy Nieznany
Czę¶ć ogólna PC wykład 1 wprowadzenie do PC
kurs wprow.cz.prakt.2008, Znieczulenie, Wykłady-Wprowadz. do spcjalizacji w anestezjologii i int.ter
Budownictwo Ogolne I zaoczne wyklad 1 wprowadzenie b
Wykład 1 - Wprowadzenie - 01.03.2011 r, studia
Wykład 2 Wprowadzenie do telefonii internetowej
WYKLAD I - wprowadzenie modele baz danych, Uczelnia, sem V, bazy danych, wyklad Rudnik
Wykład WPROWADZENIE DO EKONOMII
WYKŁADY Z WPROWADZENIA DO PEDAGOGIKI
Psychologia ogólna - Historia psychologii - wykład 1 - Wprowadzenie do historii psychologii, Wykład
wyklad 1 - wprowadzenie do prawoznawstwa, Studia UE Katowice FiR, I stopień, semestr I, Prawo Szpor
Wykład 1[1] WPROWADZENIE
Alina Kolańczy - Wprowadzenie do psychologii (wykłady), wprowadz w6, WYKŁAD IV
Wykład I- Wprowadzenie, Rozdział 2 - Hipotezy przepływu

więcej podobnych podstron