Podstawy programowania obiektowego Dariusz Rataj

background image

Podstawy

programowania
obiektowego

Ćwiczenia laboratoryjne nr 1

Temat: Wstęp do programowania obiektowego

Prowadzący:

mgr inż. Dariusz Rataj

Koszalin 2001

background image

Podstawy programowania obiektowego

Strona 2

Skrócony spis treści:

Część 1 - Programowanie obiektowe w języku C++

Część 2 - Programowanie obiektowe w środowisku Borland C++Builder

1. Programowanie obiektowe w języku C++

1.1. Cel programowania obiektowego

Programowanie obiektowe jest próbą "przeniesienia" rzeczywistości na platformę maszyn liczących zwanych

komputerami. Człowiek w życiu codziennym postrzega przedmioty (obiekty) rzeczywiste w sposób intuicyjny nie

zwracając uwagi na szczegóły zachowania czy stanu przedmiotu. W programowaniu strukturalnym programista jest

zmuszony do znajomości wielu parametrów symulowanego obiektu. Celem programowania obiektowego jest

uzyskanie możliwości wydawania poleceń dla symulowanego obiektu rzeczywistego bez konieczności zagłębiania się

w szczegóły jego konstrukcji czy stanu.

1.2. Przykład symulacji obiektu rzeczywistego

W tej części przedstawiony zostanie prosty przykład opisu obiektu rzeczywistego - samochodu. Widząc samochód

jadący ulicą przeciętny człowiek zwróci uwagę jedynie na ogólne cechy pojazdu, np.: wielkość (duży, mały), kolor

itd. Jadąc samochodem "wydajemy polecenia": przyspiesz, zwolnij, zatrzymaj itd. Opis obiektu rzeczywistego na

poziomie języka programowania powinien umożliwić wydawanie tego typu poleceń. Każdy obiekt rzeczywisty

posiada trzy elementy: tożsamość (nazwa), stan lub cechy obiektu, zachowanie (działania na obiekcie).

Przykładowy samochód jest oczywiście obiektem rzeczywistym złożonym z wielu podzespołów, części i możemy
opisać go bardzo szczegółowo. W wielu zastosowaniach wystarczy nam jednak opis tylko niektórych cech obiektu.

Takie podejście do opisu (pewne cechy są istotne inne są bez znaczenia) określane są w teorii obiektowej mianem

abstrakcji. Programista operuje jedynie na pewnym poziomie abstrakcji niezbędnym do zrealizowania celu

oprogramowania, np. inaczej będzie wyglądał opis obiektu programisty piszącego grę "wyścigi samochodowe", a

inaczej opis do celów symulacji wypadków wykonany dla firmy produkującej samochody. Poniżej przedstawiony

został prosty przykład opisu obiektowego (obiektu - samochodu) demonstrujący zasady tworzenia symulacji

obiektu rzeczywistego.

Prezentowany przykład ogranicza się tylko do elementarnych cech samochodu: marka, model, kolor, pozX (pozycja

X), pozY (pozycja Y) i czterech czynności: ustawMarke, ustawModel, ustawKolor, przesun operujących na cechach.

W terminologii programowania obiektowego cechy opisujące stan obiektu będziemy nazywać polami obiektu (lub

zmiennymi składowymi obiektu) natomiast czynności nazwiemy metodami (lub procedurami i funkcjami

składowymi obiektu).

1. Tożsamość (nazwa) - samochód

2. Stan obiektu (cechy opisujące obiekt):

- Marka
- Model

- Kolor

- Pozycja (współrzędne x i y)

3. Zachowanie (działania na obiekcie):

- Nazwanie marki

- Nazwanie modelu

- Zmiana koloru

- Przesunięcie samochodu - zmiana

położenia (pozycji)

Obiekt rzeczywisty

Opis obiektu

rzeczywistego

class

samochod {

public

:

char

marka[

20

];

char

model[

20

];

int

kolor;

int

pozX, pozY;

samochod();

void

ustawMarke(

char

*s);

void

ustawModel(

char

*s);

void

ustawKolor(

int

k);

void

przesun(

int

x,

int

y);

};

Definicja typu
obiektowego

(Zgodnie ze składnią języka

programowania C++)

background image

Podstawy programowania obiektowego

Strona 3

Po zdefiniowaniu obiektu możemy wykorzystać obiekt w programie głównym. Na początek należy zdefiniować

zmienną obiektową klasy samochod:

samochod car1;

// deklaracja obiektu (utworzenie instancji obiektu)

Następnie w ciele programu głównego możemy wywołać wcześniej zdefiniowane funkcje i procedury obiektu.

Przykładowy program główny symuluje jazdę samochodu po ekranie monitora (kursory: góra, dół, prawo, lewo).

Pełny kod programu definiującego i wykorzystującego obiekt

samochod:

#include <conio.h>
#include <stdio.h>
#include <iostream.h>
#include <string.h>

class

samochod {

public

:

// pola (zmienne)

char

marka[

20

];

char

model[

20

];

int

kolor;

int

pozX, pozY;

// metody (funkcje)

samochod();

// konstruktor

void

ustawMarke(

char

*s);

// ustawienie marki samochodu

void

ustawModel(

char

*s);

// ustawienie marki samochodu

void

ustawKolor(

int

k);

// ustawienie koloru samochodu

void

przesun(

int

x,

int

y);

// przesuniecie po ekranie

};

samochod::samochod()
{
pozX =

0

; pozY =

0

;

}

void

samochod::ustawMarke(

char

*s)

{
strcpy(marka, s);

// kopiowanie parametru do zmiennej marka

cout <<

"Marka:"

<< marka << endl;

}

void

samochod::ustawModel(

char

*s)

{
strcpy(model, s);

// kopiowanie parametru do zmiennej model

cout <<

"Model:"

<< model << endl;

}

void

samochod::ustawKolor(

int

k)

{
kolor = k;

// zmiana zmiennej kolor

textcolor(k);

// zmiana koloru znaku na ekranie

cout <<

"Kolor(nr):"

<< kolor << endl;

}

void

samochod::przesun(

int

x,

int

y)

{
pozX += x; pozY += y;

// zmiana zmiennych pozX i pozY

if

(pozX >

80

) pozX=

1

;

if

(pozY >

25

) pozY=

1

;

background image

Podstawy programowania obiektowego

Strona 4

if

(pozX <

1

) pozX=

80

;

if

(pozY <

1

) pozY=

25

;

gotoxy(pozX, pozY);

// przesuniecie kursora

cprintf(

"%c"

,

'X'

);

}

void

main()

{

int

key;

clrscr();
samochod car1;

// utworzenie obiektu typu samochod

car1.ustawMarke(

"Audi"

);

car1.ustawModel(

"A4"

);

car1.ustawKolor(RED);
car1.przesun(

40

,

12

);

do

{

key = getch();

// pobranie kodu klawisza

switch

(key) {

case

72

: car1.przesun(

0

,-

1

);

break

;

// kody kursorow: gora

case

80

: car1.przesun(

0

,

1

);

break

;

// dol

case

77

: car1.przesun(

1

,

0

);

break

;

// prawo

case

75

: car1.przesun(-

1

,

0

);

break

;

// lewo

}
}

while

(key !=

27

);

// rozne od Esc

textcolor(WHITE);
clrscr();
}

2. Programowanie obiektowe w C++ Builder

2.1. Środowisko programowania pod Windows - C++ Builder

Nowoczesne środowiska programowania pod system Windows takie jak Borland C++ Builder

umożliwiają stworzenie programu okienkowego wykorzystującego gotowe obiekty zdefiniowane

w środowisku graficznym systemu operacyjnego lub w samym środowisku C++Builder. W większości

prostych zastosowań nie będzie konieczne "ręczne" definiowanie własnych obiektów tak jak ma to

miejsce w programowaniu strukturalnym. Większość mozolnej pracy (tworzenie plików, okien,
obiektów kontrolnych itp.) wykonuje za nas środowisko programowania. Proces tworzenia aplikacji

Windows w tego typu środowiskach można ująć w kilku podstawowych etapach:

a) Utworzenie projektu (nazwanie projektu, wskazanie katalogu w którym przechowywane będą

wszystkie pliki składające się na projekt). Na tym etapie tworzone jest (automatycznie) główne

okno aplikacji i główne pliki źródłowe aplikacji.

b) Dodanie obiektów kontrolnych do głównego okna aplikacji (menu, napisy, pola tekstowe,

przyciski itp.).

c) Utworzenie okien dodatkowych posiadających również obiekty kontrolne, które należy

zdefiniować (podobnie jak w głównym oknie aplikacji: patrz pkt. 2 i 3). Okna dodatkowe

najczęściej są aktywowane przez okno główne aplikacji (są aktywowane w metodach obsługi

zdarzeń obiektów kontrolnych), np.: zdarzenie "kliknięcie na przycisku" w głównym oknie aplikacji

spowoduje uruchomienie (aktywowanie) okna dodatkowego.

d) Zdefiniowanie odpowiednich "zdarzeń" i przypisanie ich do obiektów kontrolnych, np.

zdefiniowanie metody (funkcji, procedury), która zostanie wykonana po kliknięciu na przycisku.

e) Skompilowanie i uruchomienie (jeżeli nie ma błędów) oraz przetestowanie działania aplikacji.

background image

Podstawy programowania obiektowego

Strona 5

2.2. Przykład prostej aplikacji w CBuilder - "Ankieta"

Program "Ankieta" będzie umożliwiał przeprowadzenie prostej ankiety osobowej (np. ucznia, studenta)

zawierającej pytania o imię, nazwisko, wiek i klasa. Po wypełnieniu ankiety użytkownik może

wygenerować podsumowanie wykorzystujące dane z ankiety. Podsumowanie zostanie umieszczone w

dodatkowym oknie aplikacji a następnie zapisane do pliku o nazwie wybranej przez użytkownika. Do

zapisania pliku o wybranej nazwie i w wybranym katalogu na dysku można użyć standardowego
obiektu SaveDialog z grupy obiektów Dialogs.

a) Utworzenie projektu

Z menu górnego wybieramy polecenie File - New Application. Następnie polecenie File - Save

Project as.... Otworzy się okno dialogowe w którym wybieramy katalog naszego projektu i nazwę

plików (pliku źródłowego Unit1.cpp - plik okna głównego aplikacji; pliku projektu Project1.bpr). Po

wykonaniu tych czynności utworzy się puste okno główne aplikacji gotowe do edycji o nazwie Form1.

Okno główne aplikacji

Okno zapisu do pliku (okno

standardowe z grupy Dialogs)

Okno dodatkowe aplikacji

background image

Podstawy programowania obiektowego

Strona 6

b) Dodanie obiektów kontrolnych do głównego okna aplikacji

Dodawane obiekty kontrolne możemy wybrać z podręcznego menu obiektów. W głównym oknie

aplikacji "Ankieta" użyjemy obiektów kontrolnych z grupy Standard:

-

Label (tekst statyczny).

-

Edit (pole tekstowe służące do wprowadzania krótkich tekstów).

-

Button (graficzny przycisk)

c) Utworzenie okien dodatkowych - okno "Wynik ankiety"

Aby dodać okno do aplikacji wybieramy polecenie File - New Form. Utworzy się nowy obiekt okna o

nazwie Form2 (plik źródłowy Unit2.cpp). Będzie to drugie okno aplikacji - "Wynik ankiety". W drugim

oknie ("Wynik ankiety") aplikacji użyjemy obiektów kontrolnych z grupy Standard:
-

GroupBox (ramka grupująca obiekty).

-

Memo (pole tekstowe służące do wprowadzania dłuższych tekstów złożonych z kilku linii tekstu).

-

Button (graficzny przycisk) x 2.

Dodatkowo w tym oknie dodamy standardowe okno SaveDialog z grupy Dialogs (poszukać tego

obiektu). Obiekt ten (okno dialogowe zapisu do pliku) będzie nazywał się SaveDialog1.

Dodajemy także przycisk (Button) "Zamknij".

d) Zdefiniowanie zdarzeń i przypisanie ich do obiektów kontrolnych

- zdarzenia w głównym oknie aplikacji

W oknie głównym aplikacji (obiekt Form1 - "Ankieta") zdefiniujemy jedno zdarzenie - kliknięcie na

przycisku "Zapisz do pliku". W tym celu klikamy na przycisku "Zapisz do pliku" - w oknie Object

Inspector pojawią się właściwości obiektu Button. Przechodzimy do zakładki Events (zdarzenia) i

klikamy dwa razy na zdarzeniu OnClick (kliknięcie na obiekcie). Środowisko programistyczne powinno

utworzyć automatycznie metodę obsługi zdarzenia OnClick o nazwie Button1Click. Teraz definiujemy

tą metodę wpisując wewnątrz fragment kodu w języku C++:

Form1->Memo1->Text = Edit1->Text +" nazywa się "+ Edit2->Text +", ma "+

Edit3->Text +" lat i chodzi do klasy " + Edit4->Text;
Form2->ShowModal();

-

Pierwsze polecenie zmienia pole Text obiektu Memo1 okna Form2. W tym poleceniu składamy
tekst obiektu Memo1 odczytując dane (tekst) z pól Edit okna głównego. Każdy obiekt typu Edit

posiada pole Text przechowujące dane wpisane do obiektu, np.: Edit1->Text przechowuje tekst

wpisany w obiekcie Edit1 (imię ankietowanego).

-

Drugie polecenie uaktywnia drugie okno w trybie modalnym.

Wszystkie okna systemu Windows mogą pracować w dwóch podstawowych trybach:

-

Modalnym (aktywacja procedurą ShowModal),

-

Standardowym lub niemodalnym (aktywacja procedurą Show),

Label

Edit

Button

Button

Memo

GroupBox

background image

Podstawy programowania obiektowego

Strona 7

- zdarzenia w oknie "Wynik ankiety"

W oknie dodatkowym aplikacji (obiekt Form2 - "Wynik ankiety") zdefiniujemy jedno zdarzenie -

kliknięcie na przycisku "Podsumowanie". W tym celu klikamy na przycisku "Podsumowanie" - w oknie

Object Inspector pojawią się właściwości obiektu Button. Przechodzimy do zakładki Events

(zdarzenia) i klikamy dwa razy na zdarzeniu OnClick (kliknięcie na obiekcie). Środowisko

programistyczne powinno utworzyć automatycznie metodę obsługi zdarzenia OnClick o nazwie
Button1Click. Teraz definiujemy tą metodę wpisując wewnątrz fragment kodu w języku Delphi:

if (SaveDialog1->Execute()) Memo1->Lines->SaveToFile(SaveDialog1->FileName);

Obiekt SaveDialog posiada metodę Execute, która uruchamia okno dialogowe wyboru pliku na

dysku. Po zakończeniu działania okna w polu (zmiennej) FileName przechowywana jest pełna

(z pełną ścieżką dostępu) nazwa wybranego pliku. Metoda SaveToFile zapisuje tekst obiektu Memo

do wybranego pliku.

W oknie "Wynik ankiety" znajduje się (patrz: punkt c) przycisk "Zamknij". Dla tego przycisku

definiujemy pole (właściwość) ModalResult równe mrOk. MrOk jest jednym z kilku poleceń okna
otwartego w trybie modalnym i powoduje "potwierdzenie" działań wykonanych w oknie. W naszym

przykładzie spowoduje zamknięcie okna.

e) Skompilowanie, uruchomienie i przetestowanie aplikacji

Po wykonaniu wszystkich wyżej opisanych działań możemy skompilować i uruchomić aplikację. W tym

celu wybieramy polecenie z menu górnego Run - Run. Następnie należy sprawdzić czy wszystkie

zaprogramowane działania wykonują się poprawnie:

-

wypełniamy ankietę,

-

klikamy przycisk "Podsumowanie",

-

klikamy przycisk "Zapisz do pliku" okna "Wynik ankiety",

-

wybieramy katalog i podajemy nazwę pliku do którego chcemy zapisać dane - polecenie "Zapisz"

okna SaveDialog,

-

teraz można pozamykać okna i zakończyć działanie aplikacji,

-

korzystając z dowolnego edytora tekstowego systemu Windows (np. Notatnik) sprawdzamy: czy

został poprawnie utworzony plik tekstowy i czy zawiera poprawny tekst wynikowy ankiety.

2.3. Zadanie do samodzielnego wykonania - "Prosta przeglądarka
graficzna"

Utworzyć program (aplikację) Windows:

Obiekt

Image

Menu górne
obiekt typu

Menu

Grafika
umieszczona
w obiekcie

Image

background image

Podstawy

programowania
obiektowego

Ćwiczenia laboratoryjne nr 2

Temat: Konstruktory, destruktory, funkcje zaprzyjaźnione

Prowadzący:

mgr inż. Dariusz Rataj

Koszalin 2001

background image

Podstawy programowania obiektowego ćw nr 2

Strona 2

Spis treści:

1. Konstruktor przeciążony, destruktor obiektu

2. Hermetyzacja - ukrywanie informacji

1. Konstruktor przeciążony, destruktor obiektu

Dla każdej klasy mamy możliwość utworzenia kilku konstruktorów. Może to być konstruktor
bezparametrowy i konstruktor z parametrami. Jeżeli klasa nie posiada zdefiniowanego
konstruktora to kompilator automatycznie doda konstruktor bezparametrowy. Możemy
także samodzielnie zdefiniować działanie konstruktora bezparametrowego. Przykład 1
definiuje klasę Plik otwierającą plik dyskowy do zapisu. Zdefiniowany został konstruktor
bezparametrowy - tworzący plik o nazwie wbudowanej (default.txt) oraz konstruktor
z parametrem - nazwą pliku dyskowego.

Deklaracja zmiennej obiektowej

Plik plik1(

"proba.txt"

);

// konstruktor z parametrem - nazwa pliku

wywoła konstruktor z parametrem i utworzy plik dyskowy o nazwie proba.txt.

Deklaracja zmiennej obiektowej

Plik plik2;

// konstruktor bezparametrowy - plik default.txt

wywoła konstruktor bezparametrowy i utworzy plik dyskowy o nazwie wbudowanej
default.txt.

Kompilator automatycznie decyduje jaki konstruktor ma być wywołany w zależności od typu
parametrów w deklaracji obiektu.
Konstruktory w przykładzie 1 wykonują operację otwarcia pliku dyskowego. W takiej
sytuacji programista ma obowiązek zadbać o to aby plik ten został zamknięty przed
zakończeniem programu. Operację tą wykonuje destruktor (~Plik). Destruktor jest
wywoływany automatycznie w sytuacji gdy obiekt jest zwalniany (kończy się czas życia
obiektu - w tym przykładzie kończy się program). Dzięki zastosowaniu destruktora
programista nie musi pamiętać (zdarza się zapomnieć:-) o zamknięciu pliku przed
zakończeniem programu. Destruktor powinien również zwalniać pamięć rezerwowaną
dynamicznie w czasie działania programu, zamykać połączenia sieciowe itp.

Przykład 1. Definicja klasy Plik, utworzenie dwóch plików dyskowych

#include <stdio.h>

class

Plik

{

private

:

FILE* plik;

// zmienna plikowa

Public

:

Plik();

// konstruktor bezparametrowy

Plik(

char

*NazwaPliku);

// konstruktor z parametrem - nazwa pliku

~Plik();

// destruktor

void

zapisz(

char

*line);

// metoda zapisujaca linie tekstu do pliku

};

// konstruktor tworzy plik o nazwie wbudowanej default.txt

Plik::Plik()
{

if

((plik = fopen(

"default.txt"

,

"wt"

)) ==

NULL

)

{
fprintf(stderr,

"Nie moge otworzyc pliku!!!.\n"

);

}
}

background image

Podstawy programowania obiektowego

Strona 3

// konstruktor tworzy plik o nazwie podanej jako parametr

Plik::Plik(

char

*NazwaPliku)

{

if

((plik = fopen(NazwaPliku,

"wt"

)) ==

NULL

)

{
fprintf(stderr,

"Nie moge otworzyc pliku!!!.\n"

);

}
}

void

Plik::zapisz(

char

*text)

{
fprintf(plik, text);

// zapis lini do pliku

fprintf(plik,

"\n"

);

// przejscie do nastepnej linii

printf(

"Zapisano do pliku: %s\n\r"

, text);

}

// destruktor zamyka plik

Plik::~Plik()
{

if

(plik) fclose(plik);

}

void

main()

{
Plik plik1(

"proba.txt"

);

// konstruktor z parametrem - nazwa pliku

Plik plik2;

// konstruktor bezparametrowy - plik default.txt

plik1.zapisz(

"--------- plik proba.txt ------------"

);

// zapis do 1 pliku

plik1.zapisz(

"proba zapisu tekstu"

);

plik1.zapisz(

"---------- koniec zapisu -------------"

);

plik2.zapisz(

"--------- plik default.txt ----------"

);

// zapis do 2 pliku

plik2.zapisz(

"proba zapisu tekstu"

);

plik2.zapisz(

"---------- koniec zapisu -------------"

);

}

2. Hermetyzacja - ukrywanie informacji

Projektant-programista ma możliwość ukrycia najbardziej niepewnych części projektu
i przez to zmniejszenia niebezpieczeństwa ewentualnych przeróbek (zmniejszenia wpływu
na pozostałe moduły projektu). W systemach obiektowych przyjęto formalny podział praw
dostępu do interfejsu (warstwy zewnętrznej):

obszar publiczny (public) widzialny dla wszystkich innych elementów projektu,

obszar chroniony (protected) widzialny tylko dla podklas danej klasy (niewidzialny

dla innych klas i funkcji),

obszar prywatny (private) widzialny dla danej klasy i klas, funkcji

zaprzyjaźnionych.

Możemy dopuścić funkcję do obszaru prywatnego klasy przez deklarację klasy jako funkcję
zaprzyjaźnioną. Funkcja zaprzyjaźniona nie jest funkcją składową klasy. W przykładzie 2
zdefiniowane zostały dwie funkcje zaprzyjaźnione: odejmij i porownaj.

Przykład 2. Definicja klasy zespolona, demonstracja działań na liczbach zespolonych

#include <iostream.h>

// cin, cout

#include <math.h>

// fabs, sqrt

#include <conio.h>

#define TRUE

1

#define FALSE

0

// deklaracja klasy (interfejs klasy)

class

zespolona

{

background image

Podstawy programowania obiektowego ćw nr 2

Strona 4

public

:

zespolona();

// konstruktor

zespolona(

double

r,

double

i =

0

);

// konstruktor

void

ustaw(

double

r,

double

i);

// ustawienie wartosci

void

drukuj();

void

czytaj();

double

modul();

double

rzecz() {

return

re; }

double

uroj() {

return

im; }

zespolona sprzez();
zespolona dodaj(zespolona z);

// funkcje zaprzyjaznione z klasa

friend zespolona odejmij(zespolona z1, zespolona z2);
friend

int

porownaj(zespolona z1, zespolona z2);

// pola prywatne

private

:

double

re, im;

};

// definicja metod

zespolona::zespolona()
{

re =

0

; im =

0

;

}

zespolona::zespolona(

double

r,

double

i)

{

re = r; im = i;

}

void

zespolona::ustaw(

double

r,

double

i)

{

re = r; im = i;

}

void

zespolona::drukuj()

{

cout <<

'('

<< re <<

", "

<< im <<

')'

;

}

void

zespolona::czytaj()

{

cout <<

"re = "

; cin >> re;

cout <<

"im = "

; cin >> im;

}

double

zespolona::modul()

{

return

(sqrt(re*re+im*im));

}

zespolona zespolona::sprzez()
{

return

zespolona(re, -im);

}

zespolona zespolona::dodaj(zespolona z)
{

return

zespolona(re+z.re, im+z.im);

}

// funkcje zaprzyjaznione odejmij i porownaj

zespolona odejmij(zespolona z1, zespolona z2)
{

return

zespolona(z1.re-z2.re, z1.im-z2.im);

}

int

porownaj(zespolona z1, zespolona z2)

{

if

( fabs(z1.re-z2.re) <

1e-10

&& fabs(z1.im-z2.im) <

1e-10

)

return

TRUE;

else

return

FALSE;

}

background image

Podstawy programowania obiektowego

Strona 5

int

main()

{

zespolona z1, z2, z3(

1

), z4(

2

,

3

);

zespolona z5 = z4;

// inicjalizacja

clrscr();
cout <<

"z1 = "

; z1.drukuj(); cout <<

"\tz1"

<< endl;

cout <<

"z2 = "

; z2.drukuj(); cout <<

"\tz2"

<< endl;

cout <<

"z3 = "

; z3.drukuj(); cout <<

"\tz3(1)"

<< endl;

cout <<

"z4 = "

; z4.drukuj(); cout <<

"\tz4(2, 3)"

<< endl;

cout <<

"z5 = "

; z5.drukuj(); cout <<

"\tz5 = z4"

<< endl << endl;

z1.czytaj();
z2.ustaw(

3

, -

4

);

z3 = z1.sprzez();
z4 = z1.dodaj(z2);
z5 = odejmij(z1, z2);
cout <<

"z1 = "

; z1.drukuj(); cout <<

"\tz klawiatury"

<< endl;

cout <<

"z2 = "

; z2.drukuj(); cout <<

"\tustaw(3, -4)"

<< endl;

cout <<

"z3 = "

; z3.drukuj(); cout <<

"\tsprzezona do z1"

<< endl;

cout <<

"z4 = "

; z4.drukuj(); cout <<

"\tz1 + z2"

<< endl;

cout <<

"z5 = "

; z5.drukuj(); cout <<

"\tz1 - z2"

<< endl << endl;

z1 = z2;

// podstawienie

cout <<

"z1 = "

; z1.drukuj(); cout <<

"\tz1 = z2"

<< endl;

cout <<

"Re(z1) = "

<< z1.rzecz() << endl;

cout <<

"Im(z1) = "

<< z1.uroj() << endl;

cout <<

"|z1| = "

<< z1.modul() << endl << endl;

if

( porownaj(z1, z2) == TRUE )

cout <<

"z1 jest rowne z2"

<< endl;

else

cout <<

"z1 jest rozne od z2"

<< endl;

cout << endl <<

"Nacisnij dowolny klawisz..."

;

getch();

return

0

;

}

Zadania do wykonania na zajęciach i w domu:

1. Zdefiniuj klasę pilka. Klasa powinna zawierać:

Pole prywatne a typu całkowitego - promień koła.

Pole prywatne kolor typu całkowitego - kolor koła.

Konstruktor bezparametrowy inicjujący wartości początkowe pól (wybrać dowolne).

Konstruktor z parametrami promień i kolor.

Metodę publiczną powierzchnia - obliczającą pole powierzchni koła.

Metodę publiczną ustawPromien - zmieniającą promien koła.

Metodę publiczną ustawKolor - zmieniającą kolor koła.

Zdefiniuj funkcję zaprzyjaźnioną porownaj - porównującą czy dwa koła mają takie same

powierzchnie i kolor.

2. Zdefiniuj klasę prostokat. Klasa powinna zawierać:

Pola prywatne a, b typu całkowitego - dlugość boków prostokąta.

Konstruktor bezparametrowy inicjujący wartości początkowe pól (wybrać dowolne).

Konstruktor z parametrami długość i wysokość prostokąta.

Metodę publiczną powierzchnia - obliczającą pole powierzchni prostokąta.

Metodę publiczną dajDlugosc - zwracającą długość prostakąta.

Metodę publiczną dajWysokosc - zwracającą wysokość prostakąta.

Zdefiniuj funkcję zaprzyjaźnioną jestKwadrat - porównującą boki prostokąta (czy jest kwadratem).

3. Zdefiniuj klasę punkt. Klasa powinna zawierać:

Pola prywatne x, y typu całkowitego - współrzędne punktu.

Konstruktor bezparametrowy inicjujący wartości początkowe pól (wybrać dowolne).

Konstruktor z parametrami: współrzędne punktu.

Metodę publiczną dajX - zwracającą wsp. x.

Metodę publiczną dajY - zwracającą wsp. y.

Zdefiniuj funkcję zaprzyjaźnioną porównaj - porównującą współrzędne dwóch punktów (czy punkty

się nakładają).

background image

Podstawy

programowania
obiektowego

Ćwiczenia laboratoryjne nr 3

zajęcia zaplanowane na 4 godziny

Temat: Operatory przeciążone, funkcje operatorowe

Prowadzący:

mgr inż. Dariusz Rataj

Koszalin 2001

background image

Podstawy programowania obiektowego ćw nr 2

Strona 2

Spis treści:

1. Przeciążanie operatorów

2. Funkcje operatorowe składowe klasy
3. Funkcje operatorowe zaprzyjaźnione

4. Przykłady

1. Przeciążanie operatorów

Przeciążanie operatora oznacza zdefiniowanie nowego działania operatora dla definiowanej
klasy. W języku C++ mamy możliwość przedefiniowania działania (przeciążenia) prawie
wszystkich operatorów. Wyjątkami są operatory:

. .* ?: :: sizeof

Tworząc nową definicję działania operatora nie zmieniamy jego działania dla typów
standardowych, np.: definiując operator + dla nowotworzonej klasy, działanie tego
operatora dla liczb typu int lub float pozostanie niezmienione. Aby zdefiniować działanie
operatora należy utworzyć funkcję operatorową.
W naszym ćwiczeniu zajmiemy się definicjami podstawowych operatorów dwu
i jednoargumentowych. Funkcje operatorowe możemy zdefiniować jako funkcje składowe
klasy lub jako funkcje zaprzyjaźnione klasy (znane z ćwiczenia nr 2).

2. Funkcje operatorowe składowe klasy

- operatory dwuargumentowe

Operator dwuargumentowy, zdefiniowany jako funkcja składowa klasy, po lewej stronie
zawsze ma argument typu definiowanej klasy. W naszym przykładzie będzie to typ
zespolona.
Przykład:

!

Deklaracja w nagłówku klasy

!

Definicja metody

zespolona zespolona::operator + (zespolona z)
{
zespolona z1(re+z.re, im+z.im);
return z1;
}

zasady stosowania:

Typ zwracany
przez operator

Słowo kluczowe
"operator"

symbol
operatora

Prawy argument
operatora
(typ identyfikator)

zespolona operator + (zespolona z);

background image

Podstawy programowania obiektowego

Strona 3

stosujemy wtedy, gdy lewy argument jest tego samego typu co klasa, np. w operatorach

+ , -, *, /, =, = =,

definicja metody operatorowej poza klasą posiada identyfikator klasy: zespolona:: , tak

samo jak każda inna metoda klasy.

- operatory jednoargumentowe

!

Deklaracja w nagłówku klasy

zespolona operator * ();

!

Definicja metody

zespolona zespolona::operator * ()
{

return zespolona(re, -im);

}

3. Funkcje operatorowe zaprzyjaźnione

Tak zdefiniowany operator po prawej i lewej stronie ma argumenty dowolnego typu.

Przykład:

!

Deklaracja w nagłówku klasy

!

Definicja metody

ostream& operator << (ostream& o, zespolona z)
{

return o << '(' << z.re << ")+(j" << z.im << ')';

}

zasady stosowania:

stosujemy wtedy, gdy lewy argument jest innego typu (może być ten sam typ) co klasa,

np. w operatorach << ,>>. Przeważnie prawy argument jest tego samego typu co
definiowana klasa,

deklaracja metody operatorowej w nagłówku klasy posiada słowo kluczowe friend

informujące, że jest to metoda zaprzyjażniona (nie jest metodą składową klasy!). W
definicji metody to słowo nie występuje.

Typ zwracany
przez operator

Słowo kluczowe
"operator"

symbol
operatora

lewy argument
operatora
(typ identyfikator)

prawy argument
operatora
(typ identyfikator)

Słowo kluczowe
"friend" - metoda
zaprzyjaźniona

friend ostream& operator << (ostream& o, zespolona

z);

background image

Podstawy programowania obiektowego ćw nr 2

Strona 4

przeważnie typ zwracany przez metodę operatorową jest taki sam jak typ lewego

argumentu (możemy przyjąć to jako zasadę). W naszym przykładzie typ ostream&
(referencja na ostream).

4. Przykłady

Przykład 1. Definicja klasy osoba. Klasa zawiera trzy pola prywatne: nazwisko, imie, pesel typu

tekstowego (tablica znaków), dwie funkcje operatorowe zaprzyjaźnione: operator wyjścia << i

operator wejścia >>.

#include <iostream.h>

// cin, cout, ostream, istream

class

osoba

{

private

:

char

nazwisko[

30

], imie[

20

], pesel[

12

];

public

:

osoba();

// operator wyjscia drukuje dane na konsoli

friend ostream& operator <<(ostream& out, osoba& o);

// operator wejscia pobiera dane z konsoli

friend istream& operator >>(istream& in, osoba& o);
};

osoba::osoba()
{
nazwisko[

0

] =

0

;

// pierwszy znak tablicy = 0 -> tekst pusty

imie[

0

] =

0

;

pesel[

0

] =

0

;

}

ostream& operator << (ostream &out, osoba& o)

// op.wyjscia

{
out << o.nazwisko <<

" "

;

out << o.imie <<

" "

;

out << o.pesel <<

" "

;

return

out;

}

istream& operator >> (istream &in, osoba& o)

// op.wyjscia

{
in >> o.nazwisko >> o.imie >> o.pesel;

return

in;

}

void

main()

{
osoba o;

// deklaracja obiektu osoba

cout <<

"\n podaj nazwisko, imie i pesel\n"

;

cin >> o;

// wprowadzenie danych do obiektu

cout << o;

// wyprowadzenie danych na ekran

}

background image

Podstawy programowania obiektowego

Strona 5

Przykład 2. Definicja klasy Plik umożliwiającą wyprowadzenie zawartości pliku na ekran. Klasa zawiera

jedno pole prywatne plik typu FILE * (struktura opisująca strumień - plik dyskowy), funkcję

operatorową zaprzyjaźnioną definiującą operator wyjścia << .

#include <stdio.h>

// FILE, fopen, fclose, ...

#include <iostream.h>

// cout, cin, ostream

class

Plik

{

private

:

FILE* plik;

public

:

Plik(

char

*NazwaPliku);

// konstruktor otwiera plik dyskowy

~Plik();

// destruktor zamyka plik dyskowy

// operator wyjscia drukuje plik na konsoli

friend ostream& operator <<(ostream& out, Plik & pl);
};

Plik::Plik(

char

*NazwaPliku)

{

if

((plik = fopen(NazwaPliku,

"rt"

)) ==

NULL

)

{
fprintf(stderr,

"Nie moge otworzyc pliku!!!.\n"

);

}
}

Plik::~Plik()
{

if

(plik) fclose(plik);

}

ostream & operator << (ostream &out, Plik &pl)

// op.wyjscia

{

char

ch;

fseek(pl.plik,

0

, SEEK_SET);

// na poczatek pliku

do

{
ch = fgetc(pl.plik);
out << ch;
}

while

(ch != EOF);

return

out;

}

void

main()

{
Plik p(

"autoexec.bat"

);

cout << p;
}

background image

Podstawy programowania obiektowego ćw nr 2

Strona 6

Przykład 3. Definicja klasy zespolona. Przykład ten jest rozszerzeniem przykładu z ćwiczenia nr 2

o szereg operatorów jedno i dwuargumentowych. Funkcje operatorowe zostały zdefiniowane jako

składowe klasy lub jako funkcje zaprzyjaźnione. Przykład do samodzielnej analizy.

#include <iostream.h>

// cin, cout, istream, ostream

#include <math.h>

// fabs, sqrt

#include <conio.h>

// clrscr, getch

typedef enum BOOL { FALSE =

0

, TRUE };

// deklaracja klasy (interfejs klasy)

class

zespolona

{

private

:

double

re, im;

public

:

zespolona() { re =

0

; im =

0

; }

zespolona(

double

r,

double

i =

0

): re(r), im(i) { }

void

ustaw(

double

r,

double

i) { re = r; im = i; }

// przeciazone operatory

zespolona operator * ();
zespolona operator + (zespolona z);
friend zespolona operator - (zespolona z1, zespolona z2);
zespolona& operator += (zespolona z);
friend ostream& operator << (ostream &os, zespolona z);
friend istream& operator >> (istream &is, zespolona &z);
friend BOOL operator == (zespolona z1, zespolona z2);

};

// definicja klasy (implementacja klasy), tzn. definicje funkcji
// skladowych klasy i funkcji zaprzyjaznionych z klasa

zespolona zespolona::operator * ()
{

return

zespolona(re, -im);

}

zespolona zespolona::operator + (zespolona z)
{

return

zespolona(re+z.re, im+z.im);

}

zespolona operator - (zespolona z1, zespolona z2)
{

return

zespolona(z1.re-z2.re, z1.im-z2.im);

}

zespolona& zespolona::operator += (zespolona z)
{
re += z.re; im += z.im;

return

*this;

}

ostream& operator << (ostream &os, zespolona z)
{

return

os <<

'('

<< z.re <<

", "

<< z.im <<

')'

;

}

istream& operator >> (istream &is, zespolona &z)
{
cout <<

"re = "

; is >> z.re;

cout <<

"im = "

; is >> z.im;

return

is;

}

BOOL operator == (zespolona z1, zespolona z2)

background image

Podstawy programowania obiektowego

Strona 7

{

if

( fabs(z1.re-z2.re) <

1e-10

&& fabs(z1.im-z2.im) <

1e-10

)

return

TRUE;

else

return

FALSE;

}

int

main()

{

zespolona z1, z2, z3(

1

), z4(

2

,

3

);

zespolona z5 = z4;

// inicjalizacja

clrscr();
cout <<

"z1 = "

<< z1 <<

"\tz1"

<< endl;

// operator << (cout, z1);

cout <<

"z2 = "

<< z2 <<

"\tz2"

<< endl;

cout <<

"z3 = "

<< z3 <<

"\tz3(1)"

<< endl;

cout <<

"z4 = "

<< z4 <<

"\tz4(2, 3)"

<< endl;

cout <<

"z5 = "

<< z5 <<

"\tz5 = z4"

<< endl << endl;

cout <<

"Podaj z1:"

<< endl;

cin >> z1;

// operator >> (cin, z1);

z2.ustaw(

3

, -

4

);

z3 = *z1;

// z3 = z1.operator * ();

z4 = z1 + z2;

// z4 = z1.operator + (z2);

z5 = z1 - z2;

// z5 = operator - (z1, z2);

cout <<

"z1 = "

<< z1 <<

"\tz klawiatury"

<< endl;

cout <<

"z2 = "

<< z2 <<

"\tustaw(3, -4)"

<< endl;

cout <<

"z3 = "

<< z3 <<

"\tsprzezona do z1"

<< endl;

cout <<

"z4 = "

<< z4 <<

"\t= z1 + z2"

<< endl;

cout <<

"z5 = "

<< z5 <<

"\t= z1 - z2"

<< endl << endl;

z4 = z1 +

2

;

// nie mozna: z4 = 2 + z1;

cout <<

"z4 = "

<< z4 <<

"\t= z1 + 2"

<< endl;

z4 = z1 -

2

;

// mozna: z4 = 2 - z1;

cout <<

"z4 = "

<< z4 <<

"\t= z1 - 2"

<< endl;

z5 = z1 + z2 +

2

-

1

- *z1 + z1 + z2 -

1.5

;

cout <<

"z5 = "

<< z5;

cout <<

"\t= z1 + z2 + 2 - 1 - *z1 + z1 + z2 - 1.5"

<< endl;

z1 = z2;

// podstawienie

cout <<

"z1 = "

<< z1 <<

"\tz1 = z2"

<< endl;

z1 += z2;

// z1.operator += (z2);

cout <<

"z1 = "

<< z1 <<

"\tz1 += z2"

<< endl;

if

(z1 == z2)

// if ( operator == (z1, z2) )

cout <<

"z1 jest rowne z2"

<< endl;

else

cout <<

"z1 jest rozne od z2"

<< endl;

cout << endl <<

"Nacisnij dowolny klawisz..."

;

getch();

return

0

;

}

background image

Podstawy programowania obiektowego ćw nr 2

Strona 8

Zadania do wykonania na zajęciach i w domu:

1. Utwórz klasę wektor - jednowymiarową tablicę wartości typu float. Klasa powinna zawierać:

pole prywatne p - wskaźnik na początek tablicy wartości typu float,

konstruktor z parametrem typu int - rozmiarem tablicy tworzący dynamicznie tablicę (new) o
odpowiednim rozmiarze,

destruktor zwalniający pamięć zarezerwowaną przez konstruktor,

funkcję operatorową >>, tak aby można było wprowadzać dane z klawiatury do wektora,

funkcję operatorową <<, tak aby można było wyprowadzać dane z wektora na ekran.

2. Utwórz klasę wektor - jednowymiarową tablicę wartości typu int. Klasa powinna zawierać:

pole prywatne tab - wskaźnik na początek tablicy wartości typy int,

konstruktor z parametrem typu int - rozmiarem tablicy tworzący dynamicznie tablicę (new) o

odpowiednim rozmiarze,

destruktor zwalniający pamięć zarezerwowaną przez konstruktor,

funkcję operatorową >>, tak aby można było wprowadzać dane z klawiatury do wektora,

funkcję operatorową <<, tak aby można było wyprowadzać dane z wektora na ekran.

3. Dla przykładu nr 2 (klasa Plik) rozszerzyć możliwości klasy o funkcje:

konstruktor przeciążony tworzący nowy plik dyskowy,

funkcje operatorową >>, tak aby można było wprowadzać dane z klawiatury do nowego pliku

dyskowego,

funkcję operatorową =, tak aby można było przypisać zawartość pliku,

funkcję operatorową +, tak aby można było dodawać zawartości dwóch plików. Wraz z

operatorem = otrzymamy możliwość wykonania działania:

void main()
{
Plik plik1("pl1.txt"), plik2("pl2.txt"), plik1("pl2.txt");
plik1 = plik2 + plik3;
}

4. Dla przykładu nr 2 (klasa Plik) rozszerzyć możliwości klasy o funkcje:

konstruktor przeciążony tworzący nowy plik dyskowy,

funkcje operatorowe <<, tak aby można było wykonać działanie:

void main()
{
float f = 2.34;
int i = 5;
char tekst[] = "Hallo - to tekst";

Plik plik1("pl1.txt");
plik1 << f;

// zapis do pliku wartości typu

float

plik1 << i; // za

pis do pliku wartości typu

int

plik1 << tekst; // zapis do pliku tekstu z tablicy
}

Uwaga!!! Konieczne jest zdefiniowanie trzech oddzielnych operatorów << dla każdego typu danych.

5. Utwórz klasę okrag - obiekt graficzny. Klasa powinna zawierać:

pola prywatne r - promień, x - wsp. x środka, y - wsp. y środka,

konstruktor z parametrami: promien, wsp. x i y środka,

metodę rysuj rysującą okrag w trybie graficznym systemu DOS,

funkcje operatorową ++ przesuwającą okrąg o 1 punkt w prawo,

funkcje operatorową -- przesuwającą okrąg o 1 punkt w lewo.

funkcje operatorową + dodającą dwa okręgi (działanie dodawania można przyjąć dowolne),

funkcje operatorową = umożliwiającą przypisanie,

funkcje operatorową == porównującą dwa okręgi.

background image

Podstawy

programowania
obiektowego

Ćwiczenia laboratoryjne nr 4

Temat: Dziedziczenie, metody wirtualne

Prowadzący:

mgr inż. Dariusz Rataj

Koszalin 2001

background image

Podstawy programowania obiektowego ćw nr 2

Strona 2

Spis treści:

1. Dziedziczenie, klasy bazowe i pochodne

2. Metody wirtualne

1. Dziedziczenie, klasy bazowe i pochodne

Dziedziczenie oznacza możliwość tworzenia nowych klas na podstawie klas już istniejących.
Inaczej mówiąc, dziedziczenie polega na przejmowaniu właściwości jednej klasy (klasy
bazowej
) przez inna klasę (klasę pochodną), np. możemy utworzyć klasę bazową
samochod i klasy pochodne ciezarowka i osobowy. Klasa samochod powinna posiadać
atrybuty (pola i metody) wspólne dla wszystkich samochodów a klasy ciezarowka i osobowy
atrybuty specyficzne dla konkretnego rodzaju samochodu. Klasy pochodne rozszerzają
możliwości klasy bazowej. Rozwijając przykład można by utworzyć klasy pochodne klas
ciezarowka i osobowy i utworzyć bardziej szczegółowy podział np. klasy klasa_S,
klasa_rodzinny, klasa_Maluch, TIR, dzwig itd.

Rys.1. Hierarchia dziedziczenia - drzewo klas samochodów

W sytuacji gdy klasa pochodna jest klasą bazową dla innych klas mówimy o dziedziczeniu
wielokrotnym
. W języku C++ dziedziczenie możemy zrealizować umieszczając w nagłówku
klasy, po dwukropku, listy nazw klas bazowych oddzielonych przecinkami, np.:

class A {...};
class B: A {...}; // klasa B dziedziczy po klasie A
class C: B {...}; // klasa C dziedziczy po klasie B

Umieszczając po dwukropku więcej niż jedną klasę:

class A {...};
class B {...};
class C: A, B {...}; // klasa C dziedziczy po klasie A i klasie B

klasa pochodna dziedziczy komponenty po dwóch (lub więcej) klasach.

Przed nazwą klasy bazowej możemy umieścić modyfikator prawa dostępu:

public

i

private

. Modyfikator public uczyni z publicznych i chronionych komponentów klasy

bazowej publiczne i chronione komponenty klasy pochodnej. Modyfikator private uczyni
z publicznych i chronionych komponentów klasy bazowej prywatne komponenty klasy
pochodnej. Komponenty prywatne klasy bazowej nie będą dostępne dla klasy pochodnej,
np.:

class A {...};
class B {...};
class C: public A, private B {...}; // C dziedziczy po klasie A i klasie B

samochod

osobowy

ciezarowka

klasa_S

klasa_rodzinny

TIR

dzwig

klasa_Maluch

background image

Podstawy programowania obiektowego

Strona 3

Komponenty publiczne i chronione klasy A będą publicznymi i chronionymi komponentami
klasy C. Komponenty publiczne i chronione klasy B będą komponentami prywatnymi klasy C
(nie będą dostępne dla klas pochodnych klasy C). Dziedziczenie po kilku klasach nazywamy
dziedziczeniem wielobazowym.

2. Metody wirtualne

Metody wirtualne pozwalają na odwoływanie się do nieistniejących jeszcze metod klas
pochodnych, które zamierzamy utworzyć w przyszłości. W przykładzie poniżej (patrz:
Przykład 1) klasa bazowa osoba posiada metodę czysto wirtualną (bez definicji działania
metody) drukuj. Jest to metoda która istnieje tylko w celu nadpisania w klasach
pochodnych. Klasy pochodne pracownik i student nadpisują metodę wirtualną drukuj
definiując jej działanie odpowiednio dla każdej klasy. W programie głównym deklarowany
wskaźnik ktos na zmienną obiektową typu osoba jest inicjowany dynamicznie przez
wywołanie konstruktora klasy pracownik a potem student.

osoba *ktos = new pracownik(

"Ewa Grabowska"

,

30

,

10

);

ktos->drukuj();
delete ktos;

ktos = new student(

"Marek Jankowski"

,

20

,

2

);

ktos->drukuj();
delete ktos;

Po każdym zainicjowaniu obiektu wywoływana jest metoda drukuj. Metoda jest wywoływana
na rzecz klasy osoba - pozornie!!! - w rzeczywistości wywoływane są odpowiednie metody
wirtualne drukuj klas pracownik i student. Dzieje się tak dzięki zadeklarowaniu metody
drukuj jako metody wirtualnej - w przeciwnym przypadku wywołanie drukuj powodowałoby
próbę wywołania metody składowej klasy osoba (która nie ma definicji tylko deklarację).

Metody wirtualne stosowane są przede wszystkim w celu rozszerzania możliwości

klas w przyszłości. W strukturach gdzie klasa bazowa posiada wiele klas pochodnych jest to
często jedyna metoda na uporządkowanie pracy ze złożonym systemem obiektów.
Przykładowo, znane wszystkim obiekty kontrolne systemu Windows (TButton, TLabel,
TMemo, TList itd.) dziedziczą po klasie TWinControl (dziedziczenie wielokrotne). Wszystkie
te obiekty posiadają inną reprezentacje graficzną. Przy każdym rysowaniu okna aplikacji
Windows wywoływana jest metoda rysująca dla wszystkich obiektów kontrolnych - metoda
Repaint klasy TWinControl. Ponieważ jest to metoda wirtualna i każda klasa pochodna
TWinControl ją nadpisuje, każdy z obiektów jest rysowany inaczej.

Metody wirtualne są praktyczną realizacją polimorfizmu w programowaniu

obiektowym (polimorfizm - wielopostaciowość). O metodach wirtualnych można powiedzieć
że są to metody, które mają wiele postaci (definicji).

background image

Podstawy programowania obiektowego ćw nr 2

Strona 4

Przykład 1. Definicja klasy bazowej osoba. Klasa zawiera pola chronione: nazwisko, wiek; metodę

czysto wirtualną drukuj. Klasy pochodne pracownik i student posiadają pola specyficzne odpowiednio

dla pracownika i studenta: stazpracy i rokstudiow. Jednocześnie metoda wirtualna drukuj została

nadpisana w obydwu klasach pochodnych.

#include <conio.h>

// clrscr, getch

#include <iostream.h>

// cout

#include <string.h>

// strcpy

// klasa bazowa abstrakcyjna

class

osoba

{

public

:

osoba(

char

*nazw,

int

w);

virtual

void

drukuj() =

0

;

// funkcja czysto wirtualna

protected

:

char

nazwisko[

20

];

int

wiek;

};

// klasa pochodna - pracownik

class

pracownik :

public

osoba

{

public

:

pracownik(

char

*nazw,

int

w,

int

staz);

virtual

void

drukuj();

private

:

int

stazpracy;

};

// klasa pochodna - student

class

student :

public

osoba

{

public

:

student(

char

*nazw,

int

w,

int

rok);

virtual

void

drukuj();

private

:

int

rokstudiow;

};

// definicje metod - klasa osoba

osoba::osoba(

char

*nazw,

int

w)

{
strcpy(nazwisko, nazw);
wiek = w;
}

// definicje metod - klasa pracownik

pracownik::pracownik(

char

*nazw,

int

w,

int

staz) : osoba(nazw, w)

{
stazpracy = staz;
}

void

pracownik::drukuj()

{
cout <<

"Nazwisko: "

<< nazwisko <<

", "

;

cout <<

"wiek: "

<< wiek <<

", "

;

cout <<

"staz pracy: "

<< stazpracy << endl;

}

// definicje metod - klasa student

student::student(

char

*nazw,

int

w,

int

rok) : osoba(nazw, w)

{
rokstudiow = rok;
}

void

student::drukuj()

{
cout <<

"Nazwisko: "

<< nazwisko <<

", "

;

cout <<

"wiek: "

<< wiek <<

", "

;

cout <<

"rok studiow: "

<< rokstudiow << endl;

}

// program glowny

void

main()

background image

Podstawy programowania obiektowego

Strona 5

{

clrscr();

// wskaznik na obiekt klasy bazowej abstrakcyjnej

osoba *ktos = new pracownik(

"Ewa Grabowska"

,

30

,

10

);

// dynamiczne wywolywanie funkcji wirtualnej drukuj

ktos->drukuj();
delete ktos;

ktos = new student(

"Marek Jankowski"

,

20

,

2

);

ktos->drukuj();
delete ktos;

cout << endl <<

"Nacisnij dowolny klawisz..."

;

getch();

}

Zadania do wykonania na zajęciach i w domu:

1. Utworzyć prosty system grafiki wektorowej rysujący różnego rodzaju obiekty graficzne. Większość

obiektów graficznych możemy wpisać w prostokąt (okrąg, elipsa, linia, prostokąt itd.). System
powinien definiować:

klasę bazową dla obiektów graficznych - graphObject, posiadającą pola chronione x, y -

współrzędne lewego rogu prostokąta; pola chronione height i width (wysokość i szerokość

prostokąta); metodę czysto wirtualną rysuj(); pola definiujące kolor itp.;

klasy pochodne klasy graphObject: linia, elipsa, okrag, prostokat. Klasy powinny nadpisywać

metodę rysuj() klasy bazowej i odpowiednio rysować obiekt wpisany w prostokąt.

Program testujący zadeklaruje tablicę wskaźników na zmienne typu graphObject:

graphObject* obiekty[20];

a następnie utworzy obiekty graficzne i narysuje, np. tak:

for (int i = 0; i<20; i+=4)
{
obiekty[i] =

new linia(...); // parametry zależne od konstruktora

obiekty[i+1] = new elipsa(...);
obiekty[i+2] = new okrag(...);
obiekty[i+3] = new prostokat(...);
}
for (int i = 0; i<20; i++) obiekty[i]->rysuj();
....
for (int i = 0; i<20; i++) delete obiekty[i];

Obiekty graficzne można zainicjować inaczej wg uznania. Gdy rozszerzymy możliwości klas o ruch

po ekranie, możliwośc skalowania obiektów to BĘDZIE TO!!!

2. Zrealizować strukturę klas jak w punkcie 1 instrukcji (klasa bazowa samochod, pochodne ...).

3. Utworzyć klasę bazową Button (klawisz, przycisk) i klasy pochodne graphButton i textButton. W

zależności od trybu pracy programu (graficzny, tekstowy) przycisk Button będzie miała inną

reprezentację (graficzną lub tekstową).


Wyszukiwarka

Podobne podstrony:
Intuicyjne podstawy programowania obiektowego0
Podstawy programowania obiektowego cw3 cpp
Podstawy programowania obiektowego, cw2 cpp
Podstawy programowania obiektowego, cw3 cpp
informatyka-programowanie obiektowe, podstawy
PROZE 3 Podstawy języka, cd programowanie obiektowe
Podstawy Programowania 04 Programowanie Obiektowe
piasecki,podstawy programowania, Definicja klasy, tworzenie obiektów
Nowa podstawa programowa WF (1)
1 Podstawy programowania dialogowego
Programowanie obiektowe(ćw) 1
nowa podstawa programowa sp
11-nkb~1, wisisz, wydzial informatyki, studia zaoczne inzynierskie, podstawy programowania, l2
2-eukl~1, wisisz, wydzial informatyki, studia zaoczne inzynierskie, podstawy programowania, l2
Zmiany w podstawie programowej w zakresie edukcji matematycznej, Wczesna edukacja, Materiały do prac
1-algo~1, wisisz, wydzial informatyki, studia zaoczne inzynierskie, podstawy programowania, l2
c-zadania-w3, wisisz, wydzial informatyki, studia zaoczne inzynierskie, podstawy programowania, kol

więcej podobnych podstron