====== Ć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]]