Программирование >>  Операторы преобразования типа 

1 2 3 [ 4 ] 5 6 7 ... 239


void fO {

MyClass<double> d: MyClass<int> 1:

d.assign(d): OK

d.assign(i): ОШИБКА: i относится к типу MyClass<int>.

но в данном случае ОБЯЗАТЕЛЕН тип MyClass<double>

Определение другого шаблона для функции позволяет обойти требование точного совпадения типов. В этом случае аргумент может иметь произвольный тип шаблона (при условии, что типы совместимы по присваиванию):

template <class Т> class MyClass {

private: Т value;

public:

template <class X> Шаблон функции позволяет

void assign (const MyClass<X>& x) { использовать другие типы value = x,getValue(): шаблонов при присваивании.

Т getValue О const { return value:

void fO {

MyCla5S<double> d; MyClass<1nt> 1;

d.ass1gn(d); OK

d.assignd); OK (тип int совместим с double no присваиванию)

Поскольку тип аргумента х функции assign теперь отличен от *this, прямой доступ к закрытым и защищенным членам MyClasso невозможен. Вместо этого приходится использовать обходные пути вроде функции getValue() из рассмотренного примера.

Шаблонный конспхруктор представляет собой особую разновидность шаблона, определяемую внутри класса. Шаблонные конструкторы обычно определяются для обеспечения неявных преобразований типов при копировании объектов. Учтите, что шаблонный конструктор не замещает стандартный копирующий конструктор. При точном соответствии типов будет сгенерирован и вызван стандартный копирующий конструктор. Пример:

template <class Т> class MyClass { publ ic:

Шаблонный конструктор с автоматическим преобразованием типа



не замещает стандартный копирующий конструктор

template <class U>

MyClass (const MyClass<U>& x):

void fC) {

MyClass<double> xd:

MyClass<double> xd2(xd): Вызывает стандартный копирующий конструктор MyClass<1nt> x1(xd); Вызывает шаблонный конструктор

В приведенном примере тип xd2 соответствует типу xd, поэтому объект инициализируется копирующим конструктором по умолчанию, с другой стороны, тип xi отличается от типа xd, поэтому объект инициализируется шаблонным конструктором. Следовательно, если вы определяете шаблонный конструктор, не забудьте также отфеделить собственный копирующий конструктор, если стандартный копирующий конструктор вас не устраивает. Другой пример шаблона, определяемого как член класса, приведен на с. 50.

Шаблоны вложенных классов

Вложенные классы тоже могут оформляться в виде шаблонов:

template <class Т> class MyClass {

template <class T2> class NestedClass:

Явная инициализация базовых типов

При явном вызове конструктора без аргументов базовые типы инициализируются нулями:

int 11: Неопределенное значение

1nt 12 - 1ntC); Переменная инициализируется нулем

Такая возможность была реализована для того, чтобы вы могли написать код шаблона, в котором величине любого типа заведомо будет присвоено некоторое значение по умолчанию. Например, в следующей функции вызов констрзгктора гарантирует, что для всех базовых типов переменная х будет инициализирована нулем:

template <class Т> void fC)

Т X = ТО:



Обработка исключений

в стандартной библиотеке С++ применяется механизм обработки исключений. С его помощью можно обрабатывать экстренные ситуации, не загромождая интерфейс функции лишними аргументами или возвращаемыми значениями. При возникновении внештатной ситуации обычная последовательность обработки данных прерывается генерированием исключения :

class Error;

void fO

if {условие) {

throw ErrorO: Создать объект класса Error и передать ) в нем информацию об исключении

Команда throw запускает процесс, называемый раскруткой стека. Иначе говоря, программа выходит из всех блоков или функций так, как обычно происходит при выполнении команды return, однако при этом управление никуда не передается. Для всех локальных объектов, объявленных в блоках, из которых выходит программа, вызываются деструкторы. Раскрутка стека продолжается до тех пор, пока не произойдет выход из main() с .завершением программы либо исключение не будет перехвачено и обработано секцией catch:

int mainC) {

try { fO:

catch (const Error&) {

... Обработка исключения

В этом примере любое исключение типа Error, возникшее в блоке try, будет перехвачено секцией catch

Объекты исключений представляют собой стандартные объекты, определяемые в виде обычных классов или базовых типов. Следовательно, вы можете переда-

Исключение завершает вызов функции, в которой оно произошло. При этом стороне, вызвавшей функцию, можно вернуть объект в виде аргумента. Тем не менее, возврат управления не может рассматриваться как своего рода обратный вызов (снизу, где была обнаружена проблема, наверх, где эта проблема решается). После обработки исключения управление нельзя вернуть обратно и продолжить выполнение функции с того места, где оно было прервано. В этом отношении обработка исключений принципиально отличается от обработки сигналов.



1 2 3 [ 4 ] 5 6 7 ... 239

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.002
При копировании материалов приветствуются ссылки.
Яндекс.Метрика