16.11.2014 Views

Programowanie obiektowe C++ Informatyka/Automatyka i ...

Programowanie obiektowe C++ Informatyka/Automatyka i ...

Programowanie obiektowe C++ Informatyka/Automatyka i ...

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Instytut Sterowania i Systemów Informatycznych<br />

Wydział Elektrotechniki, Informatyki i Telekomunikacji<br />

Uniwersytet Zielonogórski<br />

<strong>Programowanie</strong> <strong>obiektowe</strong> <strong>C++</strong><br />

<strong>Informatyka</strong>/<strong>Automatyka</strong> i Robotyka 1<br />

stopień pierwszy – tytuł inżyniera – Semestr II rok I<br />

Zbiór zadań<br />

1 Zadania powtórkowe z iteracji i rekurencji<br />

1. Opracować funkcję do obliczania wartości kombinacji według wzoru:<br />

C k n = V k<br />

n<br />

P k<br />

=<br />

n!<br />

(n − k)! · 1<br />

k! . (1)<br />

2. Opracować krótki program, który za pomocą metody całkowania prostokątów, obliczy<br />

wartość następującej całki, która przybliża wartości liczby π:<br />

∫ 1 1<br />

π = 4 dx. (2)<br />

0 1 + x2 3. Napisać funkcję obliczającą iteracyjnie wartość symbolu Newtona:<br />

( n n!<br />

=<br />

k)<br />

k!(n − k)! . (3)<br />

4. Napisać funkcję obliczającą rekurencyjnie wartość symbolu Newtona:<br />

( { n 1<br />

= ) ( ) gdy k = 0 lub k = n<br />

k)<br />

+<br />

n−1<br />

. (4)<br />

0 < k < n<br />

( n−1<br />

k−1<br />

k<br />

5. Napisać funkcję obliczającą iteracyjnie wartość symbolu Newtona, według wzorów:<br />

( ∏ n ki=1<br />

n − i + 1<br />

k∏ n − i + 1<br />

= ∏<br />

k)<br />

ki=1<br />

=<br />

. (5)<br />

i<br />

i<br />

6. Opracować krótki program, który za pomocą funkcji iteracyjnej oraz rekurencyjnej, narysuje<br />

choinkę o zadanej wysokości n o następujacym kształcie, jeśli n = 3:<br />

+<br />

+++<br />

+++++<br />

1 Zbiór zadań dotyczy kierunku informatyki/automatyki i robotyki w trybie stacjonarnym (studia dzienne)<br />

oraz w trybie niestacjonarnym (studia zaoczne).<br />

i=1


2 „Małe co nieco o wskaźnikach”<br />

1. Napisać deklaracje następujących zmiennych:<br />

(a) wskaźnik do znaku,<br />

(b) referencja do dziesięcioelementowej tablicy liczb całkowitych,<br />

(c) tablica pięciu wskaźników do liczb rzeczywistych,<br />

(d) wskaźnik do stałej całkowitej,<br />

(e) referencja do wskaźnika znaku,<br />

(f) stały wskaźnik do stałej znakowej,<br />

(g) wskaźnik pięcioelementowej tablicy liczb rzeczywistych,<br />

(h) wskaźnik funkcji o parametrze i wartości w postaci referencji do liczb całkowitych.<br />

2. Napisać deklaracje oraz zainicjalizować wskaźniki następujących funkcji:<br />

(a) int fun(char znak,int *wsk_int),<br />

(b) float* fun2(float,float),<br />

(c) funkcja o parametrze typu całkowitego, zwracająca wskaźnik do tablicy znaków<br />

[3][3],<br />

(d) funkcja o parametrach typu int i int*, której rezultatem jest referencja do znaku.<br />

3. Co oznaczają następujące deklaracje?<br />

(a) char (*r)[];,<br />

(b) char *r[10];,<br />

(c) char q(char *);,<br />

(d) char (*q)(char[]);.<br />

4. Wykorzystując notację wskaźnikową opracować funkcje:<br />

(a) strlen() - przekazującą długość napisu,<br />

(b) strcpy() - kopiującą jeden napis na drugi,<br />

(c) strcmp() - porównującą dwa napisy,<br />

(d) strcat() - łączącą dwa napisy przyjmowane jako argumenty w jeden,<br />

(e) strrev() - sprawdzającą czy dany znak występuje w napisie.<br />

5. Narysować struktury powstałe po wykonaniu poniższych ciągów instrukcji:<br />

class elem {<br />

public:<br />

data : integer;<br />

link : *elem;<br />

};


(a) elem *p = new elem; (*p).data=4; (*p).link=NULL;<br />

(b) elem *p = new elem; p->data=7; p->link=p;<br />

(c) elem *q = new elem; (*q).data=2; q->link=NULL;<br />

elem *p = new elem; p->data=1; (*p)->link=q;<br />

(d) elem *p = new elem; p->data=5;<br />

p->link = new elem; *p->link=*p;<br />

6. Napisać program, który odwzoruje w pamięci operacyjnej następujące struktury:<br />

p<br />

(a)<br />

1 5<br />

7<br />

(b)<br />

p 1 5<br />

7<br />

(c)<br />

NULL<br />

p 0 2<br />

„A”<br />

3 Wstęp do klas<br />

1. Zdefiniowano następujący zalążek klasy, reprezentujący punkt 2D:<br />

class Punkt2D {<br />

private:<br />

float x,y;<br />

public:<br />

char symbol;<br />

...<br />

};<br />

Zadeklarować oraz zdefiniować:<br />

• funkcję składową, która wyświetli symbol punktu oraz jego współrzędne na ekranie<br />

(funkcja ma mieć charakter inline),<br />

• funkcję składową inicjującą współrzędne wartościami losowymi,<br />

• konstruktor inicjujący,<br />

• funkcję składową, która znajdzie współrzędne odbicia symetrycznego punktu względem<br />

środka symetrii, który jest dany jako argument funkcji i wyświetli je na ekranie,


• funkcję składową, która doda współrzędne dwóch punktów i zwróci je jako punkt<br />

wynikowy.<br />

Zdefiniować obiekty i podać przykładowe wywołania metod. Jaka będzie różnica jeśli typ<br />

obiektu zadeklarowany zostanie jako struktura, a nie klasa?<br />

2. Zaprojektować klasę punktNd będącą uogólnieniem klasy z ćwiczenia (1) na punkty n-<br />

wymiarowe (współrzędne przechowywane powinny być w dynamicznie rezerwowanej tablicy).<br />

Zadeklarować oraz zdefiniować:<br />

(a) konstruktor inicjujący,<br />

(b) uzupełnić definicję klasy o składnik statyczny, który ma za zadanie przechowywać<br />

liczbę istniejących obiektów klasy, a następnie dokonać jego inicjalizacju,<br />

(c) funkcję składową o nazwie dodaj, realizującą dodawanie dwóch punktów,<br />

(d) funkcję globalną o nazwie dodaj, realizującą dodawanie dwóch punktów,<br />

(e) destruktor uwzględniający zwalnianie dynamicznie przydzielonej pamięci.<br />

3. Zadeklarować unię mogącą przechowywaæ elementy typu float, int i char, a następnie:<br />

(a) napisać krótki program, w którym należy zainicjalizować unię oraz zrealizowaæ operacje<br />

przypisania jej wartości różnych typów,<br />

(b) napisać funkcję składową wyświetlającą zawartość struktury,<br />

(c) rozbudować unię o pole bitowe w wielkości 2 bitów i zrealizować przypisanie wartości<br />

inicjalizującej,<br />

(d) zadeklarować unię jako anonimową, oraz zrealizować operacje z punktu (a).<br />

4. Dane są następujące definicje:<br />

class X {<br />

int i;<br />

float j;<br />

public:<br />

int fun(int i,float j){return i;};<br />

};<br />

int fun(int i, float j){return i;};<br />

X A;int i;float j;<br />

Ocenić poprawność poniższych instrukcji:<br />

• int fun(int i,int j){return i;};<br />

• int fun(int i,float j){return i;};<br />

• int fun(float j,int i){return i;};<br />

• void fun(int i,float j){};<br />

• int fun(int i,float j);


• int fun(int i,float j,float k=0){return i;};<br />

• A.fun(i,j);<br />

• A.X::fun(i,j);<br />

• ::fun(i,j);<br />

5. Skonstruować klasę wektor do przechowywania współrzędnych trójwymiarowych punktu<br />

przestrzennego, a następnie napisać funkcje składowe realizujące podstawowe działania<br />

na wektorach (suma, różnica, iloczyn skalarny, iloczyn wektorowy). Ponadto wyposażyć<br />

klasę w funkcje służące do pobierania wektora z klawiatury, generowania losowego współrzędnych<br />

oraz wyświetlania wartości na ekranie.<br />

6. Dana jest klasa o następującym szkielecie:<br />

class PascalString {<br />

char t[256];<br />

public:<br />

//... definicje konstruktorów<br />

//... pozostała część interfejsu<br />

};<br />

Zakłada się, że element zerowy łańcucha przeznaczony jest na przechowanie jego długości.<br />

Zadeklarować i zdefiniować:<br />

• definicję konstruktora: standardowego i domniemanego,<br />

• funkcje interfejsu: zwracającą długość łańcucha, wycinającą jego wybrany fragment<br />

i składajacą dwa łancuchy w jeden.<br />

7. Rozważyć następujące definicje:<br />

class nr_tel{<br />

char nr_tel[20];<br />

char nazwisko[20];<br />

char imie[12]; ...<br />

};<br />

class ksiazka_tel {<br />

static int licznik;<br />

nr_tel numery[50]; ...<br />

};<br />

Dodać niezbędne funkcje dotyczące obsługi książki telefonicznej (dodawanie nowych i<br />

usuwanie istniejących numerów, wyszukiwanie po nazwisku). Jak również klasa powinna<br />

posiadać składnik statyczny, którego zadaniem będzie sprawdzanie wolnego miejsca w<br />

książce.<br />

8. Dla następujących struktur:


union element { char a; int b; float c; };<br />

class zbior { element *wsk_liczba; ... };<br />

rozbudować klasę zbiór o metody wykonujące podstawowe operacje na zbiorach (∪, ∩, \,<br />

∈) których elementami mogą być zmienne znakowe, całkowite lub rzeczywiste.<br />

9. Napisać definicję klasy "krzywa" zawierającą dynamiczną tablicę punktów (zastosować<br />

klasę punkt z ćwiczenia (1)) na płaszczyźnie, które tworzą krzywą łamaną. Klasa ma<br />

posiadać metody dotyczące generowania krzywych losowo, wyświetlania w trybie graficznym,<br />

realizacją skalowania oraz translacji o zadany wektor, dodawania i usuwania<br />

punktów krzywej.<br />

10. Opracować klasę „Liczba”, która będzie przechowywać liczbę całkowitą, klasa będzie także<br />

zawierać informację, o dziedzinie liczby. Klasa „Liczba” powinna posiadać metody do<br />

realizacji podstawowych operacji arytmetycznych.<br />

11. Niech będzie dany typ złożony reprezentujący liczbę zespoloną:<br />

class fLiczbaZespolona {<br />

private:<br />

float Re,Im;<br />

public:<br />

// uzupełnić we własnym<br />

// zakresie ;-)<br />

};<br />

Zadeklarować i zdefiniować:<br />

(a) konstruktor inicjalizujący (zastosować listę inicjalizacyjną),<br />

(b) konstruktor domniemany,<br />

(c) metodę dodaj umożliwiającą dodanie dwóch liczb zespolonych,<br />

(d) funkcję operatorową „+” wykonującą zadanie z punktu (11c) w wersji globalnej oraz<br />

jako składową klasy,<br />

(e) funkcję operatorową „+” wykonującą dodawanie wartości rzeczywistej do liczby zespolonej,<br />

tak aby możliwa była notacja przemienna (a dokładniej: float + fLiczbaZespolona<br />

oraz fLiczbaZespolona + float), zdefiniować obiekty i napisać przykładowe<br />

wywołania funkcji.<br />

12. Dany jest przykład klasy:<br />

class wizytowka {<br />

public:<br />

char *nazw; char *imie; char *tel;<br />

};<br />

Zadeklarować i zdefiniować:


(a) konstruktor inicjalizujący (domniemany),<br />

(b) konstruktor kopiujący,<br />

(c) operator przypisania „=” umożliwiający skopiowanie zawartości obiektu,<br />

(d) destruktor.<br />

Zdefiniować obiekty i napisać przykładowe wywołania funkcji.<br />

13. Dla następującej struktury:<br />

class Macierz2D {<br />

static int pamiec;<br />

int (*T)[n][m];<br />

};<br />

Zrealizować następujące ćwiczenia:<br />

(a) zdefiniować konstruktor domniemany,<br />

(b) przeładować operator „-” w wersji jednoargumentowej oraz dwuargumentowej,<br />

(c) przeładować operator preinkrementacji oraz postinkrementacji,<br />

(d) przeładować operatory new i delete, tak aby prowadzić statystykę zużywanej pamięci.<br />

14. Przeanalizować poniższy fragment kodu<br />

#include<br />

class samochod {<br />

int filtr_powietrza;<br />

public:<br />

int akumulator, zbiornik_paliwa;<br />

//...<br />

};<br />

samochod A,B;<br />

int *wsk1;<br />

int samochod::*wsk2=&samochod::akumulator;<br />

void main() {<br />

wsk1 = &(A.akumulator);<br />

cout


(b) wsk1=&(B.filtr_powietrza);<br />

(c) wsk2=samochod::filtr_powietrza;<br />

(d) wsk2++;<br />

(e) wsk1++;<br />

15. Określić poprawność następujących deklaracji, podać również przyczyny dla których są<br />

poprawne bądź nie?<br />

(a) f(int i,int j,int k=0); f(int i,int j);<br />

(b) f(int i,char j); f(int j);<br />

(c) f(const int k); f(int k);<br />

(d) f(const int &k); f(int &k);<br />

16. Określony został zalążek następującej klasy wektor zdefiniowanej jako<br />

class wektor{<br />

int x,y,z;<br />

public:<br />

// ... pozostały interfejs<br />

};<br />

Dodać implementację następujących elementów:<br />

(a) konstruktor domniemany,<br />

(b) konstruktor inicjujący z listą inicjalizacyjną,<br />

(c) składowe funkcje operatorowe „+”, „-”, „*” umożliwiające dodawanie, odejmowanie i<br />

mnożenie wektorów,<br />

(d) funkcje z punktu (c) w wersji globalnej.<br />

17. Dla klasy string:<br />

class mystring {<br />

int roz;<br />

char *wsk;<br />

public:<br />

//...metody<br />

};<br />

Dokonać implementacji:<br />

(a) następujących konstruktorów: standardowy (z listą inicjalizacyjną), domniemany i<br />

kopiujący,<br />

(b) metody: zwracające rozmiar łańcucha, sklejające dwa łańcuchy w jeden, odwracające<br />

kolejność liter w łańcuchu i porównującą zawartość dwóch łańcuchów,


(c) destruktor,<br />

(d) funkcje operatorowe „«”, „»” oraz „=”.<br />

Czy poniższe definicje konstruktorów są poprawne? Odpowiedź uzasadnić.<br />

(a) string::string(char t[]) :<br />

wsk(new char[roz+1]),<br />

roz(strlen(t))<br />

{<br />

strcpy(wsk,t);<br />

}<br />

(b) string::string(string);<br />

18. Niech będzie dana klasa macierz zdefiniowana nastąpująco :<br />

class macierz{<br />

int liczba_wierszy, liczba_kolumn;<br />

public:<br />

float *tablica;<br />

...<br />

};<br />

Zdefiniować:<br />

(a) konstruktory inicjujący (domniemany) i kopiujący,<br />

(b) składowe funkcje operatorowe „+”, „-”, „*”, umożliwiające dodawanie, odejmowanie i<br />

mnożenie macierzy,<br />

(c) funkcje „+”, „-”, „*” realizujące przemienne dodawanie, odejmowanie i mnożenie macierzy<br />

przez skalar,<br />

(d) operator przypisania „=” umożliwiający skopiowanie macierzy,<br />

(e) funkcję składową obliczającą wyznacznik macierzy kwadratowej,<br />

(f) destruktor.<br />

19. Stosując wskaźniki do składowych klasy posortować 50 elementową wygenerowaną losowo<br />

tablicę obiektów z ćwiczenia (12) według zadanego pola (do porównania łańcuchów<br />

znaków można zastosować funkcję strcmp z pakietu string.h).<br />

20. Zaprojektować specjalny wskażnik do wartości typu całkowitego, który będzie zapamiętywać<br />

10 ostatnio wskazywanych przez niego adresów oraz 20 adresów ostatnio utworzonych<br />

egzemplarzy takiego wskażnika. Następnie przeładować operatory inkrementacji i dekrementacji<br />

dla tej klasy obiektów.


4 Podstawy techniki dziedziczenia<br />

1. Podać deklaracje klasy podstawowej oraz klas pochodnych (przeanalizować również, czy<br />

poszczególne nazwy klas są odpowiednie, czy istnieje możliwość ich zmiany na bardziej<br />

adekwatne), tak aby odzwierciedlały poniższy digraf relacji pomiędzy klasami:<br />

Każda z klas ma posiadać zadeklarowaną funkcję wyświetlającą figurę o nazwie rysuj().<br />

Zdefiniować obiekty i napisać przykładowe wywołania z zastosowaniem funkcji rysuj().<br />

2. Zadeklarować klasę podstawową oraz klasy pochodne, tak aby odzwierciedlały następujący<br />

digraf relacji pomiędzy klasami:<br />

Zrealizować ćwiczenie bez oraz ze uwzględnieniem klas wirtualnych. Zdefiniować obiekty i<br />

napisać przykładowe wywołania funkcji. Jaki jest dostęp do pól klas podstawowych bądź<br />

poprzednich w klasach pochodnych?<br />

3. Dane są klasy:<br />

class A { private: int a;};<br />

class B { protected: int b;};<br />

class C { public: int c;};<br />

class D : protected A, public B {};<br />

class E : public D, protected C {public: A::c;};<br />

class F : private E, public A {};<br />

Zrealizować następujące ćwiczenia:<br />

(a) odtworzyć diagram dziedziczenia,<br />

(b) określić kolejność wywoływania konstruktorów dla każdej z klas,<br />

(c) określić rodzaj dostępu do zmiennych a, b, c w klasach D, E oraz F .<br />

4. Dane są szkielety klas:


class motocykl { /*...*/ } M, *wsk_M;<br />

class Honda: public motocykl {<br />

/*...*/} H, *wsk_H;<br />

class Ducati: public motocykl {<br />

/*...*/} D, *wsk_D;<br />

class Składak: public Honda, public Ducati {<br />

/*...*/} S, *wsk_S;<br />

Wskazać które z poniższych zestawów instrukcji są błędne, a które poprawne odpowiedź<br />

uzasadnić?<br />

(a) M=H;wsk_H=wsk_M;<br />

(b) D=M;wsk_D=wsk_M;<br />

(c) M=H;wsk_M=wsk_H;<br />

(d) H=S;wsk_M=wsk_S;<br />

(e) D=H;wsk_H=wsk_S;<br />

(f) M=S;wsk_S=&D;<br />

5. Dana jest klasa:<br />

class fLiczbaZespolona {<br />

private:<br />

float Re,Im;<br />

public:<br />

// uzupełnić we własnym<br />

// zakresie ;-)<br />

};<br />

oraz funkcja operatorowa:<br />

fLiczbaZespolona operator+( fLiczbaZespolona, fLiczbaZespolona);<br />

Zdefiniować konstruktor konwertujący tak, by poprawne były wyrażenia:<br />

licz_zesp z1,z2;<br />

float a=2.5;<br />

z1=z2+a; z2=a+z1;<br />

6. Uzupełnić klasę string:<br />

class string<br />

int roz;<br />

char *wsk;<br />

public:<br />

// ...metody<br />

};


o funkcję operatorową:<br />

ostream& operator


Dodatkowo obiekt każdej klasy zawiera w sobie po jednym obiekcie klas, od których<br />

bezpośrednio dziedziczy. Przykładowo, obiekt klasy E, dla której klasami podstawowymi<br />

są A, B oraz C, posiada jako komponenty po jednym elemencie typu A, B i C. Dla<br />

każdej z klas zdefiniować konstruktor i destruktor, a następnie w programie głównym<br />

przetestować kolejność ich wywoływania dla obiektu każdego z zadeklarowanych typów.<br />

10. Niech będzie dany następujący typ danych:<br />

class Tablica1D {<br />

protected:<br />

int rozmiar1;<br />

int *tab;<br />

};<br />

reprezentujący dynamiczną tablicę jednowymiarową. Do klasy dodać następujące elementy:<br />

(a) domniemany konstruktor inicjalizujący, destruktor, operator przypisania, oraz metody:<br />

wyprowadzającą zawartość tablicy na ekran, wyznaczającą wartości minimalną0<br />

i maksymalną, sortującą tablicę,<br />

(b) wykorzystać powyższą klasę i stosując mechanizm dziedziczenia napisać definicję<br />

klasy Tablica2D, która będzie posiadała takie same metody operujące na tablicy<br />

dwuwymiarowej, przy czym sortowanie oraz szukanie minimum i maksimum będzie<br />

realizowane dla każdego wiersza osobno, a wynik w przypadku wartości minimalnych<br />

oraz maksymalnych zwróci jako tablicę wartości,<br />

(c) wykorzystując klasę Tablica1D oraz Tablica2D zrobić to samo co w punkcie (b),<br />

tylko dla tablicy trójwymiarowej (sortowanie i szukanie min/max zrealizować w odniesieniu<br />

do pierwszego wymiaru tablicy).<br />

11. Zdefiniować klasę bazową Subject zawierającą trzy funkcje f(), g() i h(). Następnie z<br />

klasy tej wyprowadzić klasy Implementation1, Implementation2 oraz Proxy. Ta ostatnia<br />

powinna zawierać wskaźnik do obiektu typu Subject, a wszystkie jej metody powinny<br />

zwracać i być wywoływane na rzecz wskaźnika takiego właśnie typu obiektu. Konstruktor<br />

klasy Proxy powinien inicjalizować wskaźnik do typu Subject zainstalowanego w jej<br />

wnętrzu. W programie głównym zdefiniować dwa różne obiekty Proxy, posiadające inną<br />

implementację. Następnie zmodyfikować klasę Proxy w sposób umożliwiający dynamiczną<br />

zmianę implementacji tej klasy.


5 Polimorfizm oraz funkcje wirtualne<br />

1. Dla schematu dziedziczenia A → B → C:<br />

(a) zdefiniować klasy przy założeniu, że klasa A ma być klasą abstrakcyjną,<br />

(b) wyposażyć wszystkie klasy w wirtualną metodę nazwa zwracającą nazwę klasy,<br />

(c) dodać destruktory wirtualne,<br />

(d) dodać funkcję globalną zaprzyjaźnioną z klasą A, tak aby mogła wykonać to samo<br />

co funkcje z podpunktu (b).<br />

2. Napisać definicję klasy z trzema przeładowanymi funkcjami wirtualnymi. Stworzyć nową<br />

klasę dziedzicząca po pierwszej, z tylko jedną przeładowaną funkcją wirtualną. Utworzyć<br />

obiekt klasy pochodnej i odpowiedzieć na następujące pytania:<br />

(a) Czy można wywołać wszystkie trzy bazowe funkcje poprzez obiekt klasy pochodnej<br />

i ewentualnie w jaki sposób?<br />

(b) Czy po zrzutowaniu adresu klasy pochodnej na adres klasy bazowej można wywołać<br />

wszystkie funkcje?<br />

(c) Czy po usunięciu definicji funkcji w klasie pochodnej można wykonać podpunkt (a)?<br />

3. Poprawić błędy w programie, a następnie przeanalizować jego działanie.<br />

#include |<br />

| void main() {<br />

using namespace std; | X ob1;Y ob2; Z ob3;<br />

| ob2.fun1; ob2.fun2;<br />

class X { |<br />

public: | X *wsk = &ob2;<br />

static int x1; | wsk->fun1(); wsk->fun2();<br />

void virtual fun1() | wsk->X::fun1(); wsk->X::fun2();<br />

{ coutfun2();<br />

| wsk->X::fun1(); wsk->Z::fun2();<br />

class Y: public X { | }<br />

public: |<br />

void virtual fun1() |<br />

{ cout


Każda z klas powinna posiadać funkcje wirtualne rysuj(), przesun() oraz obrot().<br />

Dokonać wirtualnego wywołania tych funkcji dla różnego typu obiektów.<br />

6. Napisać klasę zawierającą dwie metody wykonujące to samo zadanie, jedną w wersji<br />

wirtualnej, a drugą niewirtualnej. Dodać nową klasę dziedziczącą ze wspomnianej klasy,<br />

a następnie porównać czasy wywołania każdej z funkcji (posłużyć się np. funkcją clock()<br />

— plik nagłówkowy time.h).<br />

7. Napisać krótki program obrazujący róźnicę pomiędzy wywołaniem funkcji wirtualnej wewnątrz<br />

normalnej funkcji składowej klasy, a wywołaniem funkcji wirtualnej wewnątrz<br />

konstruktora. Program powinien pokazać, że takie dwa wywołania generują róźne wyniki.<br />

8. Dane są klasy bazowe rezystor, kondensator i cewka. Wyprowadzić z nich klasy pochodne:<br />

cewka rzeczywista i kondensator rzeczywisty, a z nich z kolei układ RLC. Mając do dyspozycji<br />

tak przygotowany zestaw elementów prostych, zdefiniować układ_rez zawierający<br />

dynamiczną tablicę wskaźników do takich obiektów. Wyznaczyć charakterystykę rezonansową<br />

w zadanym przedziale częstotliwości dla szeregowego i równoległego połączenia<br />

elementów.<br />

6 Formatowanie strumieni<br />

1. Dana jest następująca definicja klasy:<br />

class X { int a[2]; };<br />

Przeładować operatory aby możliwe się stało wczytywanie i wysyłanie do standardowego<br />

strumienia obiektów klasy X.<br />

2. Napisać manipulatory dla klasy iostream:<br />

(a) bezargumentowy mający za zadanie dorzucenie przed wyświetlaną zmienną napisu<br />

„zmienna :”,<br />

(b) jednoargumentowy lin(n), który ma za zadanie przejść n razy do nowej linii.<br />

3. Otworzyć strumień wejściowy dla pliku i przepisać go do strumienia wyjściowego skojarzonego<br />

z innym plikiem.<br />

4. Dla przykładowych strumieni:<br />

ifstream in; ofstream out;<br />

(a) powiązać strumień wejściowy z wyjściowym, tak aby każda zmiana w strumieniu<br />

wejściowym odzwierciedlona była w strumieniu wyjściowym,<br />

(b) zlikwidować wiżzanie pomiędzy standardowymi strumieniami wejściowym i wyjściowym,<br />

(c) przemianować standardowe strumienie wejścia i wyjścia tak, aby dane z cin płynęły<br />

do out, a dane z in płynęły do cout.


5. Otworzyć plik poprzez utworzenie obiektu typu ifstream o nazwie in. Następnie utworzyć<br />

obiekt os typu ostrstream i przekopiować do niego całą zawartość otwartego pliku (użyć<br />

metodę rdbuf). Zamienić wszystkie litery w os na duże i zachować wynik w nowym pliku,<br />

po czym zwolniæ pamięć zajętą przez ten strumieñ.<br />

6. Napisać program, który dopisze na początku i na końcu wszystkich plików żródłowych z<br />

rozszerzeniem *.h komentarz dotyczący praw autorskich.<br />

7. Otworzyć plik o nazwie podanej jako argument programu. Następnie wyświetlić wszystkie<br />

jego linie zawierające jedno ze słów podanych jako następne argumenty wraz z numerami<br />

wierszy odpowiadającymi im w pliku.<br />

8. Dodać nowe manipulatory dla standardowego strumienia wyjściowego:<br />

(a) bin(x) wyświetlający liczbę całkowitą x w systemie binarnym,<br />

(b) bin2(x) wyświetlający liczbę zmiennoprzecinkową x w systemie binarnym,<br />

(c) convert(x, n) wyświetlający liczbę całkowitą x w systemie o podstawie n,<br />

(d) convert2(x, n) wyświetlający dziesiętnie liczbę całkowitą x podaną w systemie o<br />

podstawie n.<br />

9. W oparciu o strumienie napisać program, który podzieli plik o dużych rozmiarach na<br />

zestaw mniejszych plików. Następnie opracować program, odwracający ten proces tzn.<br />

skleić z powrotem pliki w jeden wynikowy.<br />

7 Szablony<br />

1. Opracować szablon funkcji do wyznaczania iloczynu dwóch argumentów:<br />

(a) zrealizować funkcję szablonową w wersji normalnej i operatorowej,<br />

(b) dodać funkcję wyspecjalizowaną dla tablic jednowymiarowych reprezentujących wektory<br />

(np.: 3,4,5,... elementowe),<br />

(c) wprowadzić domniemany parametr szablonu określający rozmiar tablicy.<br />

2. Przeanalizować poniższe deklaracje:<br />

int i1;<br />

const int i2;<br />

float f1,f2;<br />

template int fun(T, T*);<br />

template U fun (T, T*,U);<br />

int fun(int, int*);<br />

int fun(double, double*,double=0.0);<br />

Rozstrzygnąć, która z funkcji zostanie wywołana, gdy w programie pojawia się polecenie:<br />

(a) i1=fun(i2,&i1);


(b) f1=fun(f2,&f2);<br />

(c) f1=fun(f2,&f2,0.0);<br />

(d) i1=fun(i2,&f2);<br />

3. Zdefiniować szablon klas, przechowujący wskaźnik do pewnego obiektu. Wyposażyć go w<br />

metodę show() wyświetlający wartość tego wskaźnika oraz konstruktor rezerwujący dla<br />

niego pamięć. Pokazać przykładowe deklaracje obiektów wykorzystujących ten szablon.<br />

4. Zrealizować na prostych przykładach dziedziczenie:<br />

(a) klasy szablonowej przez zwykłą klasę,<br />

(b) szablonu klas przez zwyklą klasę,<br />

(c) klasy szablonowej przez szablon klas,<br />

(d) szablonu przez inny szablon,<br />

(e) zwykłej klasy przez specjalizowaną klasę szablonową,<br />

(f) klasy szablonowej przez inną klasę szablonową.<br />

5. Stworzyć szablon funkcji fibonacci() umożliwiający wyznaczanie kolejnych elementów ciągu<br />

Fibonacciego dla różnego typu argumentów (np.: long, float etc.).<br />

6. Stworzyć szablon funkcji sortującej tablicę liczb. Dodać możliwość sortowania także tablic<br />

łańcuchów.<br />

7. Opierając się na szablonie klasy z zadania 2 wyposażonej dodatkowo w funkcje liczenia<br />

sumy oraz sumy kwadratów elementów, wyprowadzić dwuwymiarową tablicę liczb dowolnego<br />

typu z przeładowanymi metodami z klasy bazowej. Sprawdzić działanie polimorfizmu<br />

dla tych klas.<br />

8. Zaprojektować szablon klasy przechowującej dane w postaci listy, z metodami dotyczącymi<br />

dodawania oraz usuwania elementu, przeładowanym operatorem [] pozwalającym<br />

na pracę z listą tak jak z tablicą i wyświetlaniem zawartości. Ponadto zrealizować metodę<br />

znajdującą adres ostatniego elementu na liście w taki sposób, by mogła pracować z<br />

dowolnym typem przez nią zwracanym.<br />

8 Wyjątki<br />

1. Stworzyć klasę z odpowiednią funkcją składową, zgłaszającej wyjątk. Utworzyć także klasę<br />

celem wykorzystania jej jako obiektu wyjątku. Ma ona zawierać pojedynczy wskaźnik<br />

char* reprezentujący komunikat opisujący wyjątek. Wyposażyć ją w inicjalizujący konstruktor<br />

domniemany, uzupełniający treść komunikatu. Napisać blok obsługujący wyjątek<br />

poprzez wyprowadzenie na ekran treści komunikatu.<br />

2. Przeanalizować poniższy fragment programu i wyjaśnić jaka będzie wartość zmiennej i w<br />

przypadku, gdy obiekt E, jest typu:


(a) const int E,<br />

(b) int *E,<br />

(c) int &E,<br />

(d) float E,<br />

(e) int *&E,<br />

(f) const float & const E<br />

//...<br />

int i=1;<br />

try{<br />

try{<br />

throw E;}<br />

catch(int &){i++;throw;}<br />

catch(const int){i+=2;}<br />

catch(float *){i-=2;}<br />

catch(int *){i--;throw;}}<br />

catch(int *){i*=2;}<br />

catch(int){i--;}<br />

catch(...){i--;}<br />

//...<br />

3. Dany jest następujący schemat dziedziczenia klas: A → B → C. W każdej z nich znajdują<br />

się wirtualne metody nazwa wyświetlające nazwę typu obiektu na rzecz którego są<br />

wywoływane. Opisać efekt działania następujących operacji:<br />

(a) try {C ob1;throw ob1;} catch(B ex1) {ex1.nazwa();}<br />

(b) try {C ob2;throw ob2;} catch(B &ex2) {ex2.nazwa();}<br />

(c) try {static C ob3;throw &ob3;} catch(A *ex3)<br />

{ex3->nazwa();}<br />

4. Utworzyć klasę z własnym operatorem new. Operator ten ma przydzielić pamięć dla<br />

wybranej losowo liczby obiektów (z przedziału od 5 do 50), a następnie zasymulować ”bląd<br />

wyczerpania pamięci” i zasygnalizować sytuację wyjątkową. Dodać statyczną metodę,<br />

która odzyska przydzieloną pamięć. Następnie utworzyć blok instrukcji programu odporny<br />

na wystąpienie tego typu wyjątku.<br />

5. Utworzyć destruktor zgłaszający wyjątęk a następnie opracować program udowadniający,<br />

że takie rozwiązanie może prowadzić do niekontrolowanego zakończenia programu przez<br />

funkcję terminate(). Wykorzystać funkcję set terminate() do prawidłowego zamknięcia<br />

programu. Następnie wykazać to samo w przypadku konstruktora kopiującego.<br />

6. Prześledzić proces zgłaszania i obsługi wyjątku przy użyciu własnej klasy z konstruktorami<br />

inicjującym oraz kopiującym dostarczającymi możliwie wyczerpujących informacji<br />

o tym jak obiekt został utworzony. Pokazać, że obiekty zgłoszonych wyjatków są odpowiednio<br />

likwidowane, natomiast gdy rzucany jest wskaźnik do obiektu dynamicznego to<br />

nie jest zwalniana przypisana mu pamięć. Zaproponować rozwiązanie tego problemu.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!