====== Ćwiczenie 3: Pojemniki - wektor ======
Ćwiczenie to jest częścią większego zadania, które będzie polegać na zaprojektowaniu **szablonów** kilku rodzajów klas pojemnikowych z wykorzystaniem **mechanizmu dziedziczenia** oraz **iteratora** dla tych klas. \\ **Ćwiczenie 3.** polegać będzie na zaprojektowaniu szablonu pojemnika typu **wektor**.
===== Po co =====
* Doskonalenie umiejętności definiowania szablonów.
* Utrwalenie umiejętności posługiwania się mechanizmami dziedziczenia, polimorfizmu.
* Zapoznanie się z podstawowymi strukturami danych.
===== Oddawanie ćwiczenia =====
* Przed oddaniem ćwiczenia, program należy przetestować używając następującego pliku main: {{:pl:dydaktyka:jimp2:2016:part2:ex:ex3.zip|}}
* Powyższy plik wymaga istnienia pliku ''aghInclude.h'' poprzez który włączane są wszystkie niezbędne pliki.
===== Przebieg ćwiczenia =====
- Definiujemy szablon klasy bazowej (**''aghContainer''**), od której będą się wywodzić pozostałe klasy pojemnikowe
- Klasa bazowa **nie może** posiadać **żadnych** pól składowych ponieważ w klasach pochodnych sposób gromadzenia i przechowywania danych może być **różny** (porównaj: wektor, lista, stos, drzewo).
- Indeksowanie elementów rozpoczynamy od **zera**.
- **Obowiązkowe** metody jakie **muszą** znaleść się w definicji szablonu klasy **podstawowej** to:
* Metodę dodawania elementu do pojemnika:
* void append(T const&);
dodająca podany jako argument obiekt typu **''T''** do pojemnika.
* Metoda wstawiania elementu do pojemnika:
* bool insert(int, T const&);
wstawiająca obiekt typu **''T''** w wybrane miejsce. Zwraca **''true''** jeżeli podane miejsce wstawienia jest **prawidłowe**, w przeciwnym wypadku zwraca **''false''**.
* Metoda podmiany elementu w pojemniku:
* bool replace(int, T const&);
podmienia obiekt typu **''T''** z obiektem na wybranym miejscu. Zwraca **''true''** jeżeli podane miejsce podmiany jest **prawidłowe**, w przeciwnym wypadku zwraca **''false''**.
* Metoda zwracająca wartość elementu:
* T& at(int) const;
zwraca wartość w pojemniku. Zakładamy że indeksowanie wartości rozpoczynamy **od zera**.
* Metoda zwracająca ilość elementów:
* int size(void) const;
zwraca ilość elementów w pojemniku.
* Metoda usuwająca wybrany element:
* bool remove(int);
usuwa element na danym miejscu. Zwraca **''true''** jeżeli podane miejsce usunięcia jest **prawidłowe**, w przeciwnym wypadku zwraca **''false''**.
* Metoda opróżniająca pojemnik:
* void clear(void);
usuwa wszystkie elementy pojemnika.
* Metoda sprawdzająca czy pojemnik jest pusty:
* bool isEmpty(void);
zwraca **''true''** jeżeli pojemnik jest pusty, inaczej **''false''**.
* Metoda wyszukująca element w pojemniku przez wartość od zadanego momentu:
* int indexOf(T const& _value, int _from = 0) const;
wyszukuje i zwraca indeks pierwszego elementu o wartości ''_value'' zaczynając od elementu ''_from''. Jeżeli takiego elementu nie ma to zwraca ''-1''.
* Metoda sprawdzająca czy dany element jest już w pojemniku:
* bool contains(T const& _value, int _from = 0) const;
zwraca **''true''** jeżeli element o wartości ''_value'' znajduje się w pojemniku inaczej zwraca **''false''**. Wyszukiwanie rozpoczyna się od elelmetnu ''_from''.
* Oraz operatory:
* Operator przypisania.
* Operator porównania:bool operator==(aghContainer const& right);
sprawdza czy zawartość pojemników jest taka sama.
* Operator nierówności:bool operator!=(aghContainer const& right);
sprawdza czy zawartość pojemników jest różna.
* Operator ''[]'':T& operator[](int n) const;
zwraca element o indeksie ''n''.
* Operator ''+='':aghContainer& operator+=(aghContainer const& right);
dopisuje wszystkie elementy z pojemnika ''right'' i zwraca referencje do **''this''**.
* Operator ''+='':aghContainer& operator+=(T const& element);
dodaje element do pojemnika i zwraca referencje do **''this''**.
* Operator ''<<'':aghContainer& operator<<(T const& element);
dodaje element do pojemnika i zwraca referencje do **''this''**.
* Operator ''<<'':aghContainer& operator<<(aghContainer const& right);
dopisuje wszystkie elementy z pojemnika ''right'' i zwraca referencje do **''this''**.
* Operator ''<<'':ostream& operator<<(ostream&, aghContainer const& right);
wypisuje zawartość pojemnika na strumień.
* Inne konieczne metody i/lub operatory wedle uznania.
- W klasie **abstrakcyjnej** (**''aghContainer''**) definiujemy **wszystkie** możliwe do zdefiniowania metody. Zaoszczędzi to sporo czasu w kolejnych ćwiczeniach przy tworzeniu klas pochodnych. Metody których ciało **nie** może zostać zdefiniowane w klasie abstrakcyjnej to: **destruktor**, **''remove''**, **''size''**, **''insert''**, **''at''**. Pozostałem metody definiujemy przy pomocy wyżej wymienionych.
- Budujemy klasę **''aghVector''**, która będzie **dziedziczyć** powyższą klasę abstrakcyjną w sposób **publiczny**. Klasa powinna obsługiwać **wszystkie** powyższe metody.
- Nie ma przymusu tworzenia metod czy też klas specjalizowanych.
- Rozmiar wektora powinien być zmieniany dynamicznie.
- Program powinien mieć budowę **modułową**.
- **Nie dublujemy** kodu, tzn. nie piszemy dwa i więcej razy kodu, który wykonuje podobne zadania - **ta kwestia będzie ważnym kryterium oceny jakości kodu**.
- Do realizacji ćwiczenia **nie można** wykorzystywać już gotowych rozwiązań (STL, boost, Qt, itp.).
- Zaistniałe nieprawidłowe sytuacje powinny zostać obsłużone poprzez wyrzucenie wyjątku przy pomocy klasy **''[[..:org:codepolicy#obsluga_wyjatkow|aghException]]''**.
- Program powinien się poprawnie kompilować i uruchomić wraz z dostarczonymi plikami z paczki {{:pl:dydaktyka:jimp2:2016:part2:ex:ex3.zip|}}.
Plik ''catch.h'' jest to [[https://github.com/philsquared/Catch|jedna z najlepszych bibliotek do pisania testów kodu w C++]]. Plik ''ex3main.cpp'' korzysta z niej do testowania dostarczonych implementacji.
Podczas implementacji klasy ''aghVector'' proszę stosować się do, tzw. [[https://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29|reguły trzech]]