Си++: различия между версиями

Содержимое удалено Содержимое добавлено
Строка 689:
=== Синтаксические особенности шаблонов ===
 
(Типа: доДо сих пор мы не касались того, а что скрывается за троеточиями в приведённыхмногочисленных примерах шаблоновкода. Между тем, чтобы вы могли написать законченный шаблон, вам нужно узнать несколько вещей.)
 
==== Определение функций-членов (методов) ====
 
Как и всегда, определить небольшой метод можно и внутри класса:
template <typename T>
class Foo {
void bar () {
… … …
}
};
 
Возможно, это плохой стиль. В любом случае, для больших методов или сложных классов вы захотите вынести определение (то есть тело функции) наружу. Тогда вам придётся использовать такой синтаксис:
template <typename T>
void Foo <T>::bar () {
… … …
}
 
Он может показаться ужасным, но иного выхода нет. Кроме того, если вы класс определяете в заголовочном файле, то и ''все'' определения его методов вы должны поместить в заголовочный файл, а не в соответствующий «<tt>.cpp</tt>». (Как правило, у шаблонных классов вообще нет «<tt>.cpp</tt>»-файла, весь код помещается в «<tt>.h</tt>»-файл.)
 
==== Конструктор и деструктор ====
 
Конструктор и деструктор определяются также, как и обычные методы:
==== Определение данных-членов (атрибутов) ====
template <typename T>
void Foo <T>::Foo () {
… … …
}
template <typename T>
void Foo <T>::~Foo () {
… … …
}
 
Заметьте, имена конструкторов и деструктора — немногие случаи, когда имя класса употребляется «в чистом виде».
 
==== Определение статических данных-членов (атрибутов) ====
 
Если вы знаете, о чём идёт речь, то следующий пример скажет вам всё необходимое:
template <typename T>
class Foo {
public:
static int x;
};
template <class T>
int Foo <T>::x;
 
==== Экземпляр шаблона как параметр другого шаблона ====
 
Мы уже видили пример того, как это делается, выше, в разделе «Значения по-умолчанию для параметров». Немного другой пример:
template <typename T>
class Foo { … };
template <typename T>
class Bar { … };
void main () {
Bar <Foo <int> > bar;
}
 
Единственный важный момент, который нужно знать: между закрывающими угловыми скобками обязательно должен быть пробел («<tt>&gt; &gt;</tt>»). Иначе компилятор будет считать их оператором поразрядного сдвига «<tt>&gt;&gt;</tt>», и выдаст много малопонятных ошибок.
 
==== Шаблон как параметр другого шаблона ====
 
Идея в том, чтобы передать не экземпляр шаблона, а сам ''шаблон'' в качестве параметра. Иногда это было бы удобно. Увы, в Си++ такое невозможно.
 
==== Ключевое слово «<tt>typename</tt>» ====
 
Рассмотрим класс:
struct Foo {
typedef int my_type;
};
 
Вся суть этого класса в том, что «<tt>Foo::my_type</tt>» обозначает некий тип. Теперь напишем шаблонный класс, использующий этот факт. (Внимание, пример неправильный!)
template <typename T>
class Bar {
T::my_type x;
};
Мы пытаемся воспользоваться типом «<tt>my_type</tt>», определённым в «<tt>T</tt>». Однако в силу некоторых причин компилятор сам не хочет понимать, что «<tt>T::my_type</tt>» в данном случае обозначает тип. Мы должны ему в этом помочь, поставив перед всеми такими типами ключевое слово «<tt>typename</tt>»:
template <typename T>
class Bar {
typename T::my_type x;
};
 
В этом фрагменте кода утверждается, что «<tt>T::my_type</tt>» — это именно тип. На современных компиляторах всегда, ссылаясь на тип, определённый внутри класса, передаваемого параметром шаблона, необходимо всегда использовать «<tt>typename</tt>».
 
==== Кусок текста на будущее ====
 
Заметьте, ''все'' определения методов шаблонного класса должны быть видны изо всех мест, где он используется. Это значит, что если вы …
 
=== Особенности компиляции шаблонов ===