You are on page 1of 40

Podstawy informatyki

dr inż. Zbigniew Waradzyn


B-1, p.120 C, Ip.

Ćwiczenie C5
Dziedziczenie i funkcje wirtualne
Elementy grafiki 2D
Zaliczanie ćwiczenia

Ćwiczenie można zaliczać:


– dzisiaj,
– na ćwiczeniach zaliczeniowych
dn. 2003-11-26.
Spotkamy się także w następnym semestrze
na zajęciach pod tytułem:

„Szablony funkcji i klas”


Co to jest dziedziczenie?

• Dziedziczenie (tworzenie klas pochodnych)


jest techniką pozwalającą na definiowanie
nowej klasy (klasy pochodnej) przy
wykorzystaniu klasy już istniejącej (klasy
podstawowej).

• Dziedziczenie jest przydatne wtedy, gdy w


programie potrzebna jest nowa klasa podobna
do klasy już istniejącej, ale różniąca się od niej
w kilku szczegółach.
Przykład tworzenia klasy pochodnej
// klasa podstawowa
class obraz {
public:
void rama() { // ciało metody rama()}
void pokaz_sie() { // ciało metody pokaz_się() (wersja A)}
} ;
// klasa pochodna
class pejzaz: public obraz {
public:
void pokaz_sie() { // ciało metody pokaz_się() (wersja B)}
int nowa() { // ciało metody nowa()}
} ;
Co nam daje utworzenie klasy pochodnej?
• metoda rama() jest dziedziczona,
• metoda pokaz_sie() jest zdefiniowana od nowa (zasłania metodę pokaz_sie()
z klasy obraz),
• można definiować nowe metody (metoda nowa()).
Definicja klasy pochodnej

Fragment programu z poprzedniego slajdu


// klasa pochodna
specyfikator dostępu
nazwa klasy podstawowej
class pejzaz: public obraz {

lista pochodzenia
public:
void pokaz_sie() { // ciało metody pokaz_się() (wersja B)}
int nowa() { // ciało metody nowa()}
} ;
specyfikator dostępu

class pejzaz: public obraz {


// .....
}

Specyfikator dostępu to jedno ze słów:


• public
• private,
• protected.
Specyfikator dostępu określa, czy dziedziczone
nieprywatne składniki klasy podstawowej (klas
podstawowych) wejdą w klasie pochodnej do części
public, protected, czy private.
Znaczenie słowa protected
Słowo protected oznacza, że składnik jest
zastrzeżony dla klas pochodnych. To znaczy,
że:
• dla wszystkich klas pochodnych od danej klasy
jest dostępny tak, jakby był public,
• dla „reszty świata” jest niedostępny – jakby był
private.
Sposób dziedziczenia składników klasy podstawowej
gdy specyfikatorem dostępu jest public, np.
class pejzaz: public obraz { ...};

Zakres klasy podstawowej Zakres klasy pochodnej

private private

protected protected

public public
Sposób dziedziczenia składników klasy podstawowej
gdy specyfikatorem dostępu jest protected, np.
class pejzaz: protected obraz { ...};

Zakres klasy podstawowej Zakres klasy pochodnej

private private

protected protected

public public
Sposób dziedziczenia składników klasy podstawowej
gdy specyfikatorem dostępu jest private, np.
class pejzaz: private obraz { ...};

Zakres klasy podstawowej Zakres klasy pochodnej

private private

protected protected

public public
Dziedziczenie kilkupokoleniowe
Dziedziczenie może być kilkupokoleniowe, tzn.
klasa pochodna może być równocześnie klasą
podstawową dla innej klasy pochodnej.
Klasa podstawowa A (dziadek)

Klasa pochodna B (ojciec)

Klasa pochodna C od pochodnej B (syn)

Klasa A jest klasą podstawową dla klasy B


Klasa A jest klasą podstawową pośrednio dla klasy C
Dziedziczenie wielokrotne
Klasa może wywodzić się bezpośrednio od więcej
niż jednej klasy. Takie dziedziczenie nazywa się
dziedziczeniem wielokrotnym.
Klasa podst. 1 (ojciec 1) Klasa podst. 2 (ojciec 2)

Klasa pochodna (syn)

Poniższa klasa portret pochodzi od klas obraz i model


class portret: public obraz, public model {
// ....
}; Bardziej rozbudowana lista pochodzenia
Przykładowy graf programu
obraz model

pejzaż portret
martwa_natura

pejzaż_morski pejzaż_górski
Tworzenie obiektów
main() {
obraz jakis_obraz;
// obiekt klasy obraz
pejzaz jakis_pejzaz;
// obiekt klasy pejzaz
// .....
}
1. Zwykłe wywołania funkcji
składowych (metod)
main() {
obraz jakis_obraz; // definicje obiektów
pejzaz jakis_pejzaz;

jakis_obraz.rama(); // metody z klasy obraz


jakis_obraz.pokaz_sie();

jakis_pejzaz.rama(); // metoda odziedziczona


jakis_pejzaz.pokaz_sie(); // metoda z klasy pejzaz
}
Wywołanie funkcji zasłoniętej
main() {
obraz jakis_obraz; // definicje obiektów
pejzaz jakis_pejzaz;
// to było już wcześniej:
jakis_pejzaz.pokaz_sie(); // metoda z klasy pejzaz
// wywołanie metody z klasy obraz
// będąc w zakresie klasy pejzaz (funkcja jest zasłonięta)
jakis_pejzaz.obraz::pokaz_sie();
}
:: operator zakresu
2. Wywołania metod z użyciem wskaźnika (1)
main() {
obraz jakis_obraz; // definicje obiektów
pejzaz jakis_pejzaz;
// definicja wskaźnika do pokazywania na obiekty klasy obraz
obraz *wsk;
// ustawienie wskaźnika – wskaźnik wskazuje obiekt klasy podstawowej
// zgodnie z definicją
wsk = & jakis_obraz;
// wywołania metod z klasy obraz przy użyciu wskaźnika
wsk -> rama();
wsk -> pokaz_sie();
}
Wywołania metod z użyciem wskaźnika (2)

Pytanie:
Czy nasz wskaźnik, zdefiniowany do pokazywania na obiekty klasy
obraz (klasa podstawowa) może też pokazywać na obiekty klasy
pejzaz (klasa pochodna)?

Odpowiedź: TAK.
Wywołania metod z użyciem wskaźnika (3)
Pytanie:
Jaki będzie efekt wykonania instrukcji:
wsk -> rama();
wsk -> pokaz_sie();
w poniższym programie?

main() {
pejzaz jakis_pejzaz;
obraz *wsk;
wsk = & jakis_pejzaz;
wsk -> rama();
wsk -> pokaz_sie();
}
Funkcje wirtualne
Program z poprzedniego slajdu z fragmentem definicji metody pokaz_sie()
class obraz { // klasa podstawowa
public:
void (virtual) pokaz_sie() { // ciało metody pokaz_się() (wersja A)}
} ;
main() {
pejzaz jakis_pejzaz;
obraz *wsk;
wsk = & jakis_pejzaz;
wsk -> rama();
wsk -> pokaz_sie();
}
Efekt wykonania instrukcji wsk -> pokaz_sie():
• funkcja z klasy podstawowej, jeśli w definicji funkcji brak słowa virtual
(zwykła funkcja),
• funkcja z klasy pochodnej, jeśli jest słowo virtual (funkcja wirtualna).
3. Funkcja globalna z argumentem
będącym referencją obiektu klasy
podstawowej (1)
// definicja funkcji globalnej
// argument to referencja obiektu klasy podstawowej
void malarz(obraz & namalowalem) {

// wywolanie funkcji skladowej na rzecz przeslanego obiektu


namalowalem.pokaz_sie();
}
Funkcja globalna z argumentem będącym
referencją obiektu klasy podstawowej (2)
Taką funkcję można wywoływać wstawiając jako argument
aktualny:
– obiekt klasy podstawowej (zgodnie z definicją),
– obiekt klasy pochodnej,
main() {
obraz jakis_obraz
pejzaz jakis_pejzaz;
// wywołania funkcji
malarz(jakis_obraz); // argumentem jest obiekt klasy podstawowej
malarz(jakis_pejzaz); // argumentem jest obiekt klasy pochodnej
Efekt wywołania funkcji przy użyciu obiektu klasy pochodnej jest analogiczny,
jak to było przy wskaźnikach. Wykonywana jest:
• funkcja z klasy podstawowej, jeśli w definicji funkcji brak słowa virtual
(zwykła funkcja)
• funkcja z klasy pochodnej, jeśli jest słowo virtual (funkcja wirtualna)
Funkcja globalna z argumentem będącym przesłanym
przez wartość obiektu klasy podstawowej
// definicja funkcji globalnej
// argument to przesłany przez wartość obiekt klasy podstawowej
void malarz(obraz namalowalem) {

// wywolanie funkcji skladowej na rzecz przeslanego obiektu


namalowalem.pokaz_sie();
}
Pytanie:
Jaki będzie efekt wykonania zaznaczonej instrukcji?
main() {
pejzaz jakis_pejzaz;
// wywołania funkcji
malarz(jakis_pejzaz); // argumentem jest obiekt klasy pochodnej
}
Grafika tekstowa (1)
1. Wykonanie każdego programu w języku C rozpoczyna się w trybie
tekstowym z białymi znakami na czarnym tle. Domniemanym
okienkiem tekstowym jest cały ekran, podzielony na wiersze i
kolumny. Najczęściej jest 25 wierszy i 80 kolumn. Lewy górny
narożnik ekranu tekstowego ma współrzędne (1,1).

2. Z okienkiem jest związany bieżący kursor, którego położenie może


być zmieniane za pomocą funkcji void gotoxy(int x, int y), gdzie x i
y są współrzędnymi nowej pozycji kursora.

3. Definicja własnego okienka tekstowego: void window(int x1, int y1,


int x2, int y2) - prostokąt, którego przeciwległe wierzchołki mają
współrzędne (x1, y1) i (x2, y2). Najmniejsze możliwe okienko ma
rozmiary 1 x 1 znak.
Grafika tekstowa (2)
4. Jeśli użyta karta oraz monitor zapewniają wyprowadzanie
kolorowe, to można uzyskać kolorowe znaki na
kolorowym tle. Wyboru kolorów można dokonać stosując
funkcje void textcolor(int Color) oraz
void textbackground(int Color), których argumentami są
liczby lub symbole odpowiadające wybranym kolorom.
5. Można także uzyskać migotanie tekstu podając jako
dodatkowy argument funkcji textcolor symbol BLINK,
np. textcolor(RED+BLINK).
6. Do wypisywania tekstów należy używać funkcji
int cprintf(const char *format, ...).
Program demonstracyjny Grafika1.C

Możliwości grafiki tekstowej przedstawia program


Grafika1.c, demonstrujący m. in.:

• tworzenie własnego okienka graficznego,


• ustawianie kursora na zadanej pozycji,
• wybór koloru tekstu i tła,
• migotanie tekstu.
Grafika punktowa (1)
Inicjalizacja karty graficznej
// ......
int Driver, Mode; // argumenty funkcji initgraph
Driver = DETECT; // automatyczne rozpoznanie karty graficznej
initgraph(&Driver, &Mode, "C:\\BORLANDC\\BGI");
if (graphresult() != grOk) exit(1);
// ...
Można dokonywać przełączania między trybem graficznym a tekstowym
stosując funkcje void restorecrtmode(void) (trybu tekstowy) i
void setgraphmode(int Mode) (powrót do trybu graficznego).

Wyłączenie trybu graficznego dokonywane jest przez wykonanie


funkcji void closegraph(void).
Grafika punktowa (2)
Po przełączeniu systemu do trybu graficznego domniemanym okienkiem jest
cały ekran. Lewy górny narożnik ekranu ma współrzędne (0, 0) - porównaj z
trybem tekstowym. Współrzędne prawego dolnego narożnika ekranu udostępniają
funkcje int getmaxx(void) i int getmaxy(void).
Z okienkiem jest związany bieżący kursor graficzny, który jest niewidoczny.
Jego współrzędne można określić korzystając z funkcji int getx(void) i int
gety(void). Przemieszczenie kursora graficznego do punktu o współrzędnych (x, y)
dokonywane jest instrukcją void moveto(int x, int y).
Użytkownik może zdefiniować własne okienko graficzne korzystając z funkcji
void setviewport(int x1, int y1, int x2, int y2, int Clip). Argumentami tej funkcji są
współrzędne okienka liczone od lewego górnego narożnika ekranu, czyli
współrzędne absolutne (globalne), przy czym (x1, y1) to współrzędne lewego
górnego narożnika okienka, a (x2, y2) – prawego dolnego. Ostatnim argumentem
funkcji jest wyrażenie logiczne Clip określające, czy wykresy wykraczające poza
okienko mają być obcinane (Clip ≠ 0), czy nie (Clip = 0).
Czyszczenie okienka graficznego realizuje funkcja void clearviewport(void).
Grafika punktowa (3)
Obsługa kolorów:
Przykładowo w poniższym fragmencie programu:
.......................
setpalette(1, RED); // wpis nr 1 aktualnej palety odpowiada kolorowi
czerwonemu
setcolor(1); // wybór koloru wskazanego przez wpis nr 1, czyli
czerwonego
line(10, 20, 100, 200); // wykreślenie odcinka w kolorze bieżącym, czyli
czerwonym
.......................
getch(); // oczekiwanie na naciśnięcie klawisza
setpalette(1, GREEN); // wpis nr 1 aktualnej palety odpowiada kolorowi zielonemu
.......................
zostanie narysowana linia w kolorze czerwonym, która po naciśnięciu dowolnego
klawisza zmieni kolor na zielony.
Grafika punktowa (4)

Teksty można wypisywać od bieżącej pozycji kursora graficznego (funkcja


void outtext(char *TextString)) lub od zadanej pozycji (funkcja
void outtextxy(int x, int y, char *TextString)).

Fragmenty programu:
moveto(100, 100);
outtext("Witaj w demonstracyjnym programie graficznym");

outtextxy(100, 400, "Aby przechodzic dalej - naciskaj dowolny klawisz");


Grafika punktowa (5)
Do wyboru kroju czcionki, kierunku wykreślania znaków tekstu i ich rozmiaru służy
funkcja void settextstyle(int Font, int Direction, int CharSize).
Fragment programu:
settextstyle(TRIPLEX_FONT, HORIZ_DIR, 1);
outtextxy(50,70, "TRIPLEX_FONT - kroj kreskowy potrojny");

Rozciąganie czcionek o krojach kreskowych uzyskiwane jest za pomocą funkcji


void setusercharsize(int xMul, int xDiv, int yMul, int yDiv). Współczynniki
rozciągania w poziomie i w pionie wynoszą odpowiednio xMul/xDiv i
yMul/yDiv. W celu uzyskania rozciągnięcia czcionki należy po wykonaniu
funkcji setusercharsize wywołać funkcję settextstyle z trzecim argumentem
wynoszącym USER_CHAR_SIZE.
Fragment programu:
setusercharsize(1, 1, 2, 1);
settextstyle(GOTHIC_FONT, HORIZ_DIR, USER_CHAR_SIZE);
outtextxy(10, 120, "b) Ta czcionka jest rozciagnieta w pionie");
Grafika punktowa (6)
Wyboru grubości i rodzaju (faktury) linii dokonuje się funkcją
void setlinestyle(int linestyle, unsigned upattern, int thickness), w której argument
linestyle określa fakturę linii (ciągła, kropkowana, itd. – wartości 0 ... 3), a argument
thickness jej grubość (możliwe wartości 1 i 3).
Jeśli parametr linestyle określa linię definiowaną przez użytkownika (stała
USERBIT_LINE, co odpowiada wartości 4), to do tworzenia faktury linii brana jest
pod uwagę wartość parametru upattern, który powinien zawierać zdefiniowany
przez użytkownika wzór linii. Każdemu bitowi tego parametru (liczba 16-bitowa)
równemu jedności będzie odpowiadać punkt rysowanej linii w aktualnym kolorze
rysowania. Przykładowo wartości 0F0Fh odpowiada linia złożona kolejno z czterech
punktów wyświetlanych i czterech nie wyświetlanych, wartości 0505h – linia
kropkowana (jeden punkt wyświetlany, następny nie, kolejny znowu wyświetlany,
itd.), zaś wartości FFFFh – lina ciągła.
Fragmenty programu:
setlinestyle(USERBIT_LINE, 0x1234, THICK_WIDTH);
line(0, getmaxy()-100, getmaxx()-100, getmaxy()-100);
Grafika punktowa (7)
Biblioteka graficzna zawiera bogaty zestaw funkcji umożliwiających rysowanie
różnych figur geometrycznych, począwszy od rysowania punktu (funkcja putpixel).
Kontury figur są zwykle rysowane kolorem bieżącym wybranym funkcją setcolor.
Niektóre funkcje graficzne:
void putpixel(int x, int y, int Color)
void line(int x1, int y1, int x2, int y2)
void linerel(int dx, int dy)
void rectangle(int x1, int y1, int x2, int y2)
void arc(int x, int y, int StAngle, int EndAngle, int Radius)
void circle(int x, int y, int Radius)
void ellipse(int x, int y, int StAngle, int EndAngle, int xRadius, int yRadius)
void drawpoly(int NumPoints, const int *PolyPoints)
Fragmenty programu:
// Generacja tablicy do narysowania lamanej uzywajac funkcji drawpoly
int poly1[10]={300,250,400,100,500,300,600,250,100,100};
Kolor=getmaxcolor();
setcolor(Kolor-11);
drawpoly(5, poly1);
Grafika punktowa (8)
Wzorzec i kolor wypełnienia mogą być określone za pomocą funkcji:
void setfillstyle(int Pattern, int Color) lub
void setfillpattern(char *Pattern, int Color).
Przykłady funkcji wykorzystujących aktualny wzorzec i kolor wypełnienia:
void floodfill(int x, int y, int Border)
void pieslice(int x, int y, int StAngle, int EndAngle, int Radius)
void fillellipse(int x, int y, int xradius, int yradius)
void sector(int x, int y, int StAngle, int EndAngle, int xRadius, int yRadius)
void bar(int x1, int y1, int x2, int y2)
void fillpoly(int NumPoints, const int *PolyPoints)
Program demonstracyjny Grafika2.C
Niektóre możliwości grafiki punktowej przedstawia program Grafika2.c,
demonstrujący m. in.:
a) załączenie trybu graficznego,
b) przełączanie między trybem graficznym a tekstowym,
c) odczyt maksymalnych współrzędnych ekranu graficznego,
d) utworzenie własnego okienka graficznego,
e) odczyt bieżącej pozycji kursora graficznego,
f) wypisywanie tekstu:
- od bieżącej pozycji kursora,
- od zadanej pozycji kursora,
- o różnych krojach i rozmiarach czcionki,
g) rysowanie punktu, linii, łuku okręgu, okręgu, łuku elipsy, prostokąta,
h) wykresy słupkowe,
i) zmiana koloru,
j) wypełnianie obszaru tłem
Program demonstracyjny Grafika3.C
Wykorzystując tryb graficzny można pisać programy rysujące
wykresy funkcji. W programie Grafika3.c podano prosty sposób
tworzenia wykresów funkcji. Wykres rysowany jest na podstawie
danych w tablic x[i] i y[i]. Tablice te mogą być wypełniane albo w
samym programie, co odbywa się tym przypadku albo przez inną
funkcję. Program Grafika3.c zawiera:
a) rysowanie obrzeży wykresu z podziałkami,
b) wypełnianie tablic współrzędnych dla linii prostej i funkcji
sin(x),
c) rysowanie wykresu linii prostej i funkcji sin(x) przy
wykorzystaniu danych z tablic.
Program ćwiczenia (1)
1. a) zdefiniować klasy podstawowe oraz pochodne wg podanego
wzoru; dodatkowo w każdej klasie funkcja składowa pokaz_sie()
ma wykonywać odpowiedni rysunek (grafikę można uzupełnić na
końcu, najpierw umieścić tylko tekst),
b) utworzyć po jednym obiekcie podanych klas,
c) na rzecz każdego z tych obiektów zrealizować zwykłe
wywołania metod z klasy podstawowej i klas pochodnych,
d) z zakresu ważności klasy pejzaz_morski wywołać funkcję
pokaz_sie() zdefiniowaną w tej klasie oraz zasłonięte funkcje
pokaz_sie() zdefiniowane w klasach obraz oraz pejzaz.
Program ćwiczenia (2)
2. Wywoływać funkcje składowe zdefiniowane w klasie podstawowej
i w klasach pochodnych za pomocą wskaźnika do pokazywania na
obiekty klasy podstawowej – sprawdzić efekt wykonania programu
zależnie od tego, czy funkcja składowa jest wirtualna, czy nie.

3. Utworzyć funkcję o zasięgu globalnym, której argumentem


formalnym jest referencja obiektu klasy podstawowej. Wywoływać
tę funkcję globalną wstawiając jak argument kolejno utworzone
wcześniej obiekty różnych klas – sprawdzić efekt wykonania
programu podobnie, jak przy wskaźnikach.

4. Zmienić tak definicję funkcji globalnej, aby jej argumentem


formalnym był obiekt klasy obraz przekazywany przez wartość.
Sprawdzić działanie programu.
Dziękuję za uwagę

Tę prezentację można znaleźć na stronie


http://galaxy.uci.agh.edu.pl/~waradzyn/

You might also like