Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ТООП конспект весь.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
22 Мб
Скачать
☆

Int main(){

Int x;

X = f();

Double b;

D = f();

}

Невозможно. Одна и та же функция, шаблон делает недопустимую замену.

Решение:

X=f(); -> x = f<int>();

D=f(); -> d = f<double>();

Помимо обобщенных алгоритмов можно делать обобщенные структуры данных.

Шаблоны классов

List -> List<int> (List<char *>)

Пример:

Шаблоны класса стека.

Template <typename T>

Class Stack{

T * data;

Const int maxSize;

Int top;

Public:

stack(int ms = 100):maxSize(ms), top(-1),data(new T[ms]){}

T pop(); //если стек пустой, то тогда исключение

T top(); //то же самое, что и выше

Void push (T elem);

Bool isEmpty(){return top==-1;}

~Stack(){delete [] data;}

};

Template <typename P> //имя типа может и не совпадать с прошлым описанием

P stack<P>::pop(){ if (isEmpty()) throw -1; return data[top--];}

Template <typename T>

T Stack<T>::top(){

If (isEmpty()) throw -1;

Return data[top];

}

Template <typename T>

Void Stack<T>::push(T elem){

If (top==maxSize -1) throw 1000000;

Data [++top]=elem;

}

Int main(){

Stack<int> st(10);

St.push(-1);

St.push(100);

Cout<<”top =”<<st.top()<<endl;

}

Steck<double> s2; -несовместим с s1.

К методу pop не произошло обращение в процессе работы примера, апотому компилятор и не создавал его вообще.

Шаблоны могут быть вложенными, т.е. внутри шаблона одного класса можно объявлять другой шаблон другого класса. Можно внутри обычного класса объявить шаблон вложенного класса.

Дружественные функции для шаблона класса

Для шаблона класса можно объявить дружественную функцию, дружественный внешний шаблон функции и дружественный связанный шаблон функции.

Void friend Fun();

Template <typename T>

Void friendTempl();

Template <typename T>

Class A{

Stack T sta;

T a;

Friend void friendFun();

Template <typename P> friend void friendTmpl();

};

Template <typename T> T A<T>::sta;

Чтобы шаблон дружественной функции связать с шаблоном класса, в котором он объявлен, нужно в имени этой функции явно указать имя параметра шаблона класса.

Пример

Операция помещения в поток для шаблона класса.

Template <typename T> class A;

Template <typename T> ostream& operator << (ostream&, A<T>);

Template <typename T>

Class A{

T a;

Public: A(T x=T()):a(x){}

Привязка

Friend ostream& operator << <T> (ostream& o, A<T> x);

}

Template <typename T> ostream& operator << (ostream& o, A<T> x){ return o<<x.a;}

Параметры шаблонов классов могут быть типами, не типами и шаблонами.

Пример

Использование параметра не типа для шаблона стека.

Template <typename T, int maxSize>

Class stack{ T data [maxSize]; (1)

…

Если задано не typename, а конкретное название типа, то такой параметр замещается константой указанного типа.

Int main(){

Stack <int,10> st;

Stack<int,100> st2;

}

Типы разные, не совместимы.

Ограничения не типов:

Не-тип может быть не любым типом, а только:

  1. Целочисленным

  2. Перечислимым

  3. Ссылкой

  4. Указателем

(1)

Class Stack{

T data[maxSize];

Int top;

Public:

Stack():top(-1){}

…

};

Дальше в реализации ничего не меняется, но не нужен деструктор и будет работать чуть быстрее.

Чаще всего адреса (указатели) не помещаются напрямую в контейнер. Вместо этого используют прием, инициализация как выделение ресурсов.

Class A{

Char *s;

Public:

A(char *str){ s=strdup(str);}

~A(){free (s){}

Char & open for[](int I, char u){return s[i];}

}

};

A a1(u);

A1[0]=A;

Char ch=a[0];

Stack<A> s2;

S2.push(A(“Hello”));

Для шаблона параметр шаблона может заменяться массивом и в этом случае становится плохо. Это ссылка.

Template <>

Class Stack(int a[]), int b[]){…};

Template <typename T>

Class Stack{

T* *data;

…

}

Template <typename T, int maxSize>

Class Stack2;