- •6Vpj7-h3cxh-hbtpt-x4t74-3yvy7
- •Оглавление
- •Предисловие
- •Введение
- •1.1. Понятие класса и объекта. Инкапсуляция
- •1.2. Определение классов. Компоненты. Доступность
- •Class_key /*class_id*/ { /*members_list*/ };
- •Value_type class_id::function_id(parameters) {statements}
- •CPoint point1(100,70); // локальный объект
- •Static cPoint point3(50,120); // статический объект
- •Class_id(parameters) /*:initializer_list*/ {/*statements*/}
- •CString(const char *);
- •Delete[] __thematrix;
- •1.4. Обращение к компонентам объектов
- •1.5. Статические и нестатические компоненты классов
- •1.7. Указатель this
- •В опросы для самопроверки
- •2. Механизм наследования. Полиморфизм
- •2.1. Формы наследования. Базовые и производные классы
- •Class_key class_id: inheritance_specifier base_class_id {member_list};
- •2.3. Абстрактные классы
- •2.4. Множественное наследование и виртуальные классы
- •2.5. Преобразование динамических типов. Динамическая идентификация типов
- •Catch ( std::bad_cast & ) { // обработка исключения
- •Return 0;
- •Вопросы для самопроверки
- •3. Дружественные функции и классы
- •3.1. Дружественные функции
- •3.2. Дружественные классы
- •Вопросы для самопроверки
- •4. Механизм вложения
- •4.1. Вложенные классы
- •4.2. Локальные классы
- •Вопросы для самопроверки
- •5. Объектная модель и шаблоны
- •5.1. Определение, описание и инстанцирование шаблонов
- •::Function_id(function_parameter_list) { statements }
- •5.2. Параметры и аргументы шаблонов
- •Class identifier typename identifier
- •// Key, Data – параметры-типы (типы ключа и данных отображения)
- •// Container – контейнер, где содержится информация отображения class сMap {
- •Class MyTemplate
- •Int array[10]; struct Structure { int m; static int sm; } str;
- •5.3. Шаблоны компонентных функций
- •Value_type function_template_id(function_parameter_list) { statements }
- •::Function_template_id(function_parameter_list) { statements }
- •5.4. Специализация шаблонов
- •Вопросы для самопроверки
- •6. Перегрузка операций
- •Value_type operator @ (parameter_list);
- •Value_type operator @ (parameter_list) { statements }
- •Return fail();
- •6.3. Перегрузка бинарных операций
- •Value_type operator @ (parameter); // компонентная функция
- •Value_type operator @ (parameter, parameter); // глобальная функция friend value_type operator @ (parameter, parameter); // дружественная функция
- •Return *this;
- •Return *this;
- •/* Присваиваем собственные данные класса d */
- •6.4. Перегрузка операций управления памятью
- •Typedef void (*new_handler) ();
- •Extern new_handler set_new_handler( new_handler new_p );
- •Void operator delete(void * memory) {
- •... // Специальная обработка пользователя ::operator delete(memory); // освободить память
- •Вопросы для самопроверки
- •7. Механизм исключений
- •Throw expression
- •7.3. Специальные средства поддержки механизма исключений
- •Unexpected_function set_unexpected(unexpected_function func_name);
- •Typedef void (* unexpected_function) ();
- •Extern char * __throwExceptionName; extern char * __throwFileName; extern unsigned __throwLineNumber;
- •Вопросы для самопроверки
- •8. Подсчет ссылок
- •8.1. Назначение механизма подсчета ссылок
- •8.2. Контекстно-независимая модель счетчика ссылок
- •8.4. Внедрение подсчета ссылок в существующий класс
- •Вопросы для самопроверки
- •9. Стандартная библиотека шаблонов (stl)
- •9.1. Назначение и архитектура stl
- •9.2. Последовательные контейнеры
- •Class vector {
- •// Определение итераторов
- •Sort(first,last); // сортировка вектора в диапазоне итераторов
- •Ifstream ifile ("example.In"); ofstream ofile ("example.Out");
- •OutputIterator copy(
- •InputIterator first, InputIterator last, OutputIterator result );
- •// Заполнение списка
- •Operator- (int)
- •Operator- (random access iterator) operator[] (int)
- •InputIterator find(InputIterator first, InputIterator last, const t & value);
- •InputIterator find(InputIterator first, InputIterator last, const t & value)
- •Return first;
- •OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
- •Return result;
- •OutputIterator transform (InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op)
- •Return result;
- •Void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
- •__Quick_sort_loop(first, last, comp); __final_insertion_sort(first, last, comp);
- •T accumulate(InputIterator first, InputIterator last, t init, Function f);
- •V.Push_back(2); V.Push_back(5);
- •9.5. Функторы
- •T operator()(const t & X) const { return -X; }
- •9.7. Адаптеры
- •S1.Push(1); s1.Push(5);
- •// Записать в вектор числа 1 2 3 4
- •// Сортировать по неубыванию
- •// Записать в вектор числа 4 6 10 3 13 2
- •Вопросы для самопроверки
- •Заключение
- •Библиографический Список
- •6Vpj7-h3cxh-hbtpt-x4t74-3yvy7
5.4. Специализация шаблонов
Специализация шаблона классов – это механизм, в какой-то мере противоположный самому механизму шаблонов. Действительно, цель введения шаблона – построить обобщенный вариант класса, функции или компонента. Цель специализации – определение частного случая для заданного шаблона. Специализация необходима тогда, когда определение класса (функции, компонента), инстанцируемого от шаблона, отличается от общего случая, задаваемого этим шаблоном. Например, свойства класса векторов CVector<bool>, вполне вероятно, будут отличны от свойств классов CVector<double> и CVector<int>. Например, CVector<bool> может инкапсулировать поразрядные логические операции И, ИЛИ, НЕ и исключающее ИЛИ. Подобные операции вряд ли имеют смысл для классов CVector<double> и CVector<int>. Исходя из этого, после определения шаблона CVector<T> целесообразно дать специализацию CVector<bool>, в которой, в свою очередь, ввести иное определение поведения векторов.
Для специализации23 шаблонного класса используется заголовок вида template< >, за которым следует определение класса для заданных аргументов шаблона. Специализация возможна лишь после того, как определен или, по крайней мере, объявлен сам шаблон, но до того, как осуществляется инстанцирование шаблона для аргументов специализации. Формат специализации шаблонного класса таков:
template<> class_key template-id class_declaration
где template-id представляет собой полное имя шаблонного класса для аргументов специализации: class_template_id <class_template_argument_list>.
Пример
template<class T> class CStream; // описание шаблона потоков
...
template<> class CStream<char> { /* ... */ }; // специализация для char
После такой специализации класс CStream<char> будет использован для представления потоков символов char; для потоков других типов будут использоваться классы, непосредственно (явно либо неявно) инстанцируемые от шаблона.
Приведенный ниже пример показывает более детально, как определить специализацию шаблона CVector, представляющего векторы, для компонент типа bool.
template <class T> class СVector // определение шаблона
{
T * __data; // данные вектора
int __size; // длина вектора
public:
explicit СVector(int); // конструктор
CVector(const CVector<T> &); // копирующий конструктор
~CVector( ) { delete[] __data; } // деструктор
T& Item (int i) { return __data[i]; } // получение i–го элемента
...
};
template <> class СVector<bool> // специализация
{
bool * __data; // данные
int __size; // размер
public:
explicit CVector(int); // конструктор
CVector(const CVector<bool> &); // копирующий конструктор
~CVector( ) { delete[] __data; } // деструктор
bool Item (int i) { return __data[i]; } // получение элемента
CVector<bool> NOT(void) const; // поразрядное отрицание
CVector<bool> AND(const CVector<bool> &) const; // поразрядное И
...
};
// внешнее определение функции
CVector<bool> CVector<bool>::NOT(void) const
{
CVector<bool> Result(*this);
for(int i = 0; i < __size; i++)
Result.__data[i] = !Result.__data[i];
return Result;
}
...
Специализация шаблона может быть полной или частичной. Приведенный выше пример – полная специализация. При частичной специализации, в отличие от полной, сохраняется «элемент» обобщения; иными словами, частичная специализация – это то же шаблон. Отличие частичной специализации от полной по формату касается только имени: в частичной специализации именем является полный идентификатор шаблона, а в полной – обычный идентификатор. Ниже даны примеры частичных специализаций шаблона классов:
// исходный шаблон
template <class T1, class T2, int I> class A { /* ... */ };
// частичная специализация 1
template <class T1, class T2, int I> class A<T1*,T2,I> { /* ... */ };
// частичная специализация 2
template <class T, int I> class A<T*,T,I> { /* ... */ };
// частичная специализация 3
template <class T> class A<int,T*,5> { /* ... */ };
Специализация (как полная, так и частичная) допустима не только для шаблонных классов в целом, но и для их отдельных компонент: например, статических данных, функций, шаблонов компонентных функций и вложенных шаблонов классов. Формат полной специализации для компонентной функции следующий:
template<>
value_type class_template_id<class_template_argument_list>
::function_id(function_parameter_list) { statements }
Пример
template <class T> class OneClass { // определение шаблона
public:
void f(const T &);
...
};
// специализация компонентной функции
template <> void OneClass<AnotherClass>::f(const AnotherClass & o) { }
После такой специализации функция f класса OneClass будет вести себя иным способом, если аргументом шаблона будет класс AnotherClass. При других типах аргумента поведение функции будет определяться ее обобщенным внешним определением.
Формат полной специализации шаблона компонентных функций имеет следующий вид:
template<> template<>
value_type class_template_id<class_template_argument_list>
::function_template_id<function_template_argument_list>
(function_parameter_list) { statements }
Ниже представлены еще несколько примеров полной и частичной специализации.
Пример
template<class T> struct A { // исходный шаблон
void f(T &);
void h(const T *);
template<class X> void g(const T &, X *);
};
// полная специализация компонентной функции
template<> void A<int>::f(int & ri) { /* ... */ }
// определение компонентного шаблона
template<class T> template<class X>
void A<T>::g(const T & crt, X * px) { /* ... */ }
// частичная специализация компонентного шаблона
template<> template<class X>
void A<double>::g(const double & crd, X * px) { /* ... */ }
// полная специализация компонентного шаблона
template<> template<>
void A<double>::g<int>(const double & crd, int * pi) { /* ... */ }
template<> template<>
void A<double>::g(const double & crd, char * pi) { /* ... */ }
// неявно выводится A<double>::g<char>