Программирование >>  Решение нетривиальных задач 

1 ... 58 59 60 [ 61 ] 62 63 64 ... 77


public:

derived( const derived &r );

const derived &operator=( const derived &r );

-----------------------------------------------------

derived::derived( const derived &r ) : base(r), s(r.s)

-----------------------------------------------------const derived &derived:: operator=( const derived &r )

(* (base*) this) = r;

s = r.s;

Список инициализации членов в конструкторе копии описан ранее. Следующий отрывок из функции operator=() нуждается в некотором пояснении:

(* (base*)this) = r;

Указатель this указывает на весь текущий объект; добавление оператора приведения преобразует его в указатель на компонент базового класса в текущем объекте - (base*) this. (* (base*) this) является самим объектом, а выражение (* (base*) this) = r передает этому объекту сообщение, вызывая функцию operator=() базового класса для перезаписи информации из правого операнда в текущий объект. Вы могли бы заменить этот код таким образом:

base:: operator=( r );

но я видел компиляторы, которые бракуют этот оператор, если в базовом классе не объявлена явно функция operator=(). Первая форма работает независимо от того, объявлена явно operator=(), или нет. (Если не объявлена, то у вас будет по умолчанию реализовано почленное копирование).



Стандартом языка для этого предусмотрено ключевое слово explicit. - Ред.

132. Конструкторы, не предназначенные для

преобразования типов, должны иметь два или более аргумента*

Си++ использует конструкторы для преобразования типов. Например, конструктор char* в 9-ой строке листинга 7 на странице 155 также обрабатывает следующую операцию приведения:

char *pchar = абвг ; (string) pchar;

Запомните, что приведение является операцией времени выполнения, которая создает временную переменную нужного типа и инициализирует ее из аргумента. Если приводится класс, то для инициализации используется конструктор. Следующий код работает прекрасно, потому что строковая константа char* беспрепятственно преобразуется в string для передачи в функцию f() : f( const string &s );

...

f( белиберда );

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

class array

...

public:

array( int initial size );

Вероятно вы все же не захотите, чтобы следующий код работал: f( const array &a );

...

f( isupper(*str) );

(Этот вызов передает f() пустой одноэлементный массив, если *str состоит из заглавных букв, или массив без элементов, если *str - из строчных букв).

Единственным способом подавления такого поведения является добавление второго аргумента в конструктор, потому что конструкторы с несколькими аргументами никогда не используются неявно:



class array

...

public:

enum bogus { set size to }; array( bogus, int initial size );

array ar( array::set size to, 128 );

Это по настоящему уродливо, но у нас нет выбора. Заметьте, что я не дал аргументу bogus имени, потому что он используется только для выбора функции.

133. Используйте счетчики экземпляров объектов для инициализации на уровне класса

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

class window

static int num windows; public:

window(); ~window();

int window::num windows = 0; window::window()

if( ++num windows == 1 ) только что создано первое окно initialize video system();

window::~window()

if( --num windows == 0 ) только что уничтожено

shut down video system(); последнее окно

Наконец, счетчик экземпляров объектов может быть также использован в качестве счетчика числа вызовов для обеспечения инициализации на уровне подпрограммы:



1 ... 58 59 60 [ 61 ] 62 63 64 ... 77

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