Języki programowania - ćwiczenia 6
Temat zajęć: Język C++: szablony i klasy STL.
Szablony funkcji i klas
Szablony funkcji i klas są to odpowiednie fragmenty kodu parametryzowane typem danych.
W momencie implementacji szablonu co najmniej jeden typ danych, na
których operuje funkcja czy które zawiera klasa, jest
nieznany. Szablony są konkretyzowane w momencie ich użycia -
wówczas należy jawnie podać typ danych, dla którego ma
zostać utworzona funkcja czy klasa wg określonego wcześniej szablonu.
Przykład 1
Składnia definicji i wykorzystania szablonów funkcji.
Definiujemy dwa szablony: funkcji wypisującej zawartość tablicy i
funkcji sortującej tablicę.
Solution Visual Studio pobierz
Plik c7p1.cpp pobierz
#include <iostream>
using namespace std;
// definicja szablonu funkcji
template<class T>
void sortuj(T *tab, int rozm)
{
T tmp;
for (int i=0; i<rozm; i++)
for (int j=0; j<rozm-1; j++)
if (tab[j]>tab[j+1]) {
tmp = tab[j];
tab[j] = tab[j+1];
tab[j+1] = tmp;
}
}
// definicja szablonu funkcji
// w definicji szablonu typename T i class T sa tozsame
template<typename T>
void wypisz(T *tab, int rozm)
{
for (int i=0; i<rozm; i++)
cout << tab[i] << " , ";
cout << endl;
}
int main()
{
int i;
int t1[4];
double t2[5];
for (i=0; i<4; i++) {
t1[i] = 5-i;
t2[i] = 6-i;
}
t2[4] = 1;
// kompilator generuje wypisz dla T = int
wypisz<int>(t1, 4);
// kompulator generuje wypisz dla T = double
wypisz<double>(t2, 5);
// kompilator generuje sortuj dla T = int
sortuj<int>(t1, 4);
// kompilator generuje sortuj dla T = double
sortuj<double>(t2, 5);
wypisz<int>(t1, 4);
wypisz<double>(t2, 5);
return 0;
}
Przykład 2
Szablon klasy reprezentującej tablicę. Przeciążony operator indeksowania, przypisania i zapisania w strumieniu.
Solution Visual Studio pobierz
Plik c7p2.h pobierz
#pragma once
#include <iostream>
using namespace std;
template<class T>
class Array {
private:
T *buf;
int len;
public:
Array(int size);
Array(const Array<T> &a);
~Array();
T& operator[](int index) const;
int length() const;
void operator=(const Array<T> &a);
};
template<class T>
ostream& operator<<(ostream &o, const Array<T> &a);
Plik c7p2.cpp pobierz
#include "c7p2.h"
template<class T>
Array<T>::Array(int size)
{
buf = new T[size];
len = size;
}
template<class T>
Array<T>::Array(const Array<T> &a)
{
buf = new T[a.length()];
len = a.length();
for (int i=0; i<len; i++) {
buf[i] = a[i];
}
}
template<class T>
Array<T>::~Array()
{
delete[] buf;
}
template<class T>
T& Array<T>::operator[](int index) const
{
if (index < len) return buf[index];
else return buf[len];
}
template<class T>
int Array<T>::length() const
{
return len;
}
template<class T>
void Array<T>::operator=(const Array<T> &a)
{
delete[] buf;
buf = new T[a.length()];
len = a.length();
for (int i=0; i<len; i++) {
buf[i] = a[i];
}
}
template<class T>
ostream& operator<<(ostream &o, const Array<T> &a)
{
for (int i=0; i<a.length(); i++) {
o << a[i];
if (i < a.length()-1)
o << " , ";
}
return o;
}
// ----------------------------------------------------------------
int main()
{
Array<int> a(4);
Array<double> *b = new Array<double>(3);
a[0] = 1; a[1] = 2; a[2] = 3; a[3] = 4;
(*b)[0] = 1.0; (*b)[1] = 2.0; (*b)[2] = 3.0;
cout << a << endl;
cout << *b << endl;
delete b;
return 0;
}
Zadanie 1
Zaimplementować szablon funkcji, która odwróci kolejność elementów w podanym obiekcie klasy Array z przykładu 2. Przetestować funkcję na tablicach zawierających liczby całkowite i łańcuchy tekstowe.
Zmodyfikować klasę Array tak, aby możliwa była zmiana rozmiaru tablicy (dodać metodę Resize(int newsize)), przy czym zmiana rozmiaru ma zachowywać elementy w tablicy od elementu 0 do min{len, newsize}. Zmodyfikować funkcję main z przykładu 2 tak, aby sprawdzić poprawność zaimplementowanej zmiany rozmiaru tablicy.
Zadanie 2
Zaimplementować szablony klas reprezentujące listę podwójnie wiązaną. W programie powinien znaleźć się szablon klasy ListItem (pojedynczy element listy zawierający pole danych oraz wskaźniki na element poprzedni i następny) oraz szablon klasy List,
zawierający wskaźniki na głowę i ogon listy, aktualny rozmiar listy
oraz metody służące do dołączania elementów na początku i na
końcu listy oraz wyjmowania elementów z początku i końca listy.
Próba wyjęcia elementu z pustej listy powinna zwracać jako dane
domyślny element klasy parametryzujące T, czyli T().
Dodatkowo proszę zaimplementować metody wstawiające element przed i za
elementem o podanym numerze oraz operator indeksowania aby możliwy był
dostęp do elementu listy o podanym indeksie.
Zadanie 3
Zakładając, że lista z zadania 2 została zaimplementowana, proszę
zaimplementować szablon funkcji sortującej elementy listy. Funkcja jako
parametr powinna przyjmować obiekt klasy List i zwracać nowy obiekt klasy List, zawierający posortowaną listę.
Zadanie 4
Zaimplementować przeciążony operator zapisu listy do strumienia wyjściowego.
Przetestować klasy z zadań 2 i 3 oraz zaimplementowany operator zapisu
do strumienia na listach zawierających dane liczbowe (całkowite i
rzeczywiste).
Zadanie 5
Przeciążyć operator dodawania dla obiektów klasy Array z przykładu 2. Dla tablic t1 i t2 operator powinien zwracać tablicę powstałą przez dołączenie tablicy t2 na koniec tablicy t1. Same tablice t1 i t2 (operandy) powinny pozostać nietknięte.
Standard Template Library
Na bazie szablonów została zaimplementowana biblioteka STL
(Standard Template Library), która obecnie wchodzi w skład
standardowej biblioteki C++. Dokumentację STL można znaleźć np. w
plikach pomocy Borland C++ czy MS Visual C++ lub na stronach WWW, na
przykład: