Programowanie i struktury danych Programowanie i struktury danych
Wykład 8 Wykład 8
Dr Piotr Cybula <piotr.cybula@wmii.uni.lodz.pl>
Dr Piotr Cybula <piotr.cybula@wmii.uni.lodz.pl>
Struktury generyczne Struktury generyczne
Struktura tablicy dynamicznej o wartościach całkowitych:
struct Array { private:
int *array;
int size;
public:
Array(int _size = 10)
{ size = _size; array = new int[size];
} ~Array()
{ if(size > 0) delete [] array;
} int length() const { return size; }
int& operator[](int index) { return array[index]; } };
Array t(5);
t[0] = 7;
Struktury generyczne Struktury generyczne
Struktura tablicy dynamicznej o wartościach rzeczywistych:
struct Array { private:
float *array;
int size;
public:
Array(int _size = 10)
{ size = _size; array = new float[size];
} ~Array()
{ if(size > 0) delete [] array;
} int length() const { return size; }
float& operator[](int index) { return array[index]; } };
Array t(5);
t[0] = 7.5;
Programowanie generyczne Programowanie generyczne
●
realizowane w języku C++ w postaci struktur szablonowych (ang. templates)
●
szablony pozwalają na wielokrotne wykorzystanie istniejącego kodu źródłowego struktury danych dla wielu wersji tej struktury z tym samym interfejsem, ale różnymi typami dla wewnętrznych komponentów
(programowanie generyczne/uogólnione, struktury parametryzowane)
●
słowo kluczowe template jest informacją dla kompilatora, że struktura wykorzystuje nieokreślony typ danych będący parametrem tej struktury
●
podczas konkretyzacji (ang. instantiation) szablonu konkretnym typem kompilator zastępuje każde wystąpienie typu parametrycznego podanym typem i kompiluje strukturę danych (tzw. statyczny polimorfizm)
●
szablony mogą być parametryzowane typami lub wartościami (może być ich
wiele i mogą mieć wartości domyślne)
Struktura szablonowa Struktura szablonowa
Struktura tablicy dynamicznej będącej szablonem:
template<typename T> struct Array //template structure { private:
T *array; //T is a template parameter being a type int size;
public:
Array(int _size = 10)
{ size = _size; array = new T[size];
} ~Array()
{ if(size > 0) delete [] array;
} int length() const { return size; }
T& operator[](int index) { return array[index]; } };
Array<int> t1(5); Array<float> t2(10); //instantiations t1[0] = 7; t2[0] = 7.5;
Parametry szablonu Parametry szablonu
Struktura tablicy dynamicznej będącej szablonem dwuparametrowym:
template<typename T, int size = 10> struct Array //template { private:
T array[size]; //size is a template parameter being a value //size cannot be changed
public:
Array() {}
~Array() {}
int length() const { return size; }
T& operator[](int index) { return array[index]; } };
Array<int, 5> t1; //instantiation, size must be a constant Array<float> t2; //instantiation with default value for size Array<Student, 10> t3; //instantiation with a structure type t1[0] = 7;
t2[0] = 7.5;
cout << t2.length();
t3[0] = Student(”Scott Tiger”);
t3[0].setIndex(12345);
Metody szablonowe Metody szablonowe
●
przy implementacji metod struktury szablonowej poza strukturą używamy słowa kluczowego template z tymi samymi parametrami szablonu
(implementacja musi nastąpić w pliku nagłówkowym!)
template<typename T, int size>
T& Array<T, size>::operator[](int index) //template method { if(index < 0 || index >= size)
throw range_error("bad index");
return array[index];
}
//the result and the parameter types are templates template<typename T, int size>
Array<T, size>&
Array<T, size>::operator=(const Array<T, size>& arr) { if(this != &arr)
for(int i = 0; i < size; i++) array[i] = arr.array[i];
return *this;
}
Interfejs szablonu Interfejs szablonu
●
typowe określenie pasujące do szablonu: «przyjmę dowolny typ»
●
czasami implementacja metod szablonu wymusza pewne dodatkowe ograniczenia na przyjmowany typ, np. obecność pewnych metod dla typu będącego parametrem
●
ogólne określenie dla szablonu: «przyjmę dowolny typ wyposażony w ...»
Array<Student> t;
t.print(); //compile-time error, no operator<< for Student //after the declaration of the operator
ostream& operator<<(ostream &out, const Student &s) { ...
return out;
}
Array<Student> t;
t.print(); //OK
Pola szablonowe Pola szablonowe
template<typename T, int size>
struct NamedArray //structure with template field is template { private:
Array<T, size> array; //template field string name;
public:
NamedArray(string n);
T& operator[](int index);
T sum() const; //T must support operator+
T max() const; //T must support operator<
… //other methods };
NamedArray<float, 3> marks("My marks");
marks[0] = 4.5;
marks[1] = 5.0;
marks[2] = 4.0;
cout << marks.sum() / 3;
cout << marks.max();
cout << marks.length(); //compile-time error, hidden method
Szablony wielokrotne Szablony wielokrotne
●
struktura szablonowa może być parametryzowana typem szablonowym
●
w wersji kompilatora przed C++11 konieczne jest umieszczenie odstępu pomiędzy kolejnymi ostrymi nawiasami (> > zamiast >>)
//5-item array of 10-item arrays of integers //dynamic size version
Array< Array<int> > t(5);
//static size version
Array< Array<int, 10>, 5> t;
t[0][0] = 5;
cout << t.length();
cout << t[0].length();