Программирование >>  Инициализация объектов класса, структура 

1 ... 14 15 16 [ 17 ] 18 19 20 ... 395


IntArrayRC::operator[]( int index )

check range( index ); return ia[ index ];

Вот как выглядит реализация операции взятия индекса:

#include <cassert>

inline void IntArrayRC::check range(int index) {

assert (index>=0 && index < size);

А вот реализация встроенной функции check range():

(Мы говорили о макросе assert() в разделе 1.3.)

Почему проверка индекса вынесена в отдельную функцию, а не выполняется прямо в теле оператора взятия индекса? Потому что, если мы когда-нибудь потом захотим изменить что-то в реализации проверки, например написать свою обработку ошибок, а не использовать assert(), это будет сделать проще.

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

Однако заметим, что в нашем производном классе IntArrayRC нет новых членов, представляющих данные. Значит ли это, что нам не нужно реализовывать конструкторы для него? Ведь вся работа по инициализации членов данных уже проделана конструкторами базового класса.

На самом деле конструкторы, как и деструкторы или операторы присваивания, не наследуются - это правило языка С++. Кроме того, конструктор производного класса обеспечивает механизм передачи параметров конструктору базового класса. Рассмотрим

int ia[] = {0,1,1,2,3,5,8,13};

пример. Пусть мы хотим создать объект класса IntArrayRC следующим образом:

IntArrayRC iarc(ia,8);

Эта строка показывает, что класс IntArrayRC произведен от класса IntArray, другими словами, наследует ему. Ключевое слово public в данном контексте говорит о том, что производный класс сохраняет открытый интерфейс базового класса, то есть что все открытые функции базового класса остаются открытыми и в производном. Объект типа IntArrayRC может использоваться вместо объекта типа IntArray, как, например, в приведенном выше примере с функцией swap() . Таким образом, подкласс IntArrayRC -это расширенная версия класса IntArray.



inline IntArrayRC::IntArrayRC( int sz ) : IntArray( sz ) {}

inline IntArrayRC::IntArrayRC( const int *iar, int sz )

двух конструкторов IntArrayRC:

: IntArray( iar, sz ) {}

(Мы будем подробно говорить о конструкторах в главах 14 и 17. Там же м1 покажем, почему не нужно реализовывать конструктор копирования для IntArrayRC.)

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

Mi поместим все встроенн1е функции класса IntArrayRC в тот же заголовочный файл IntArrayRC.h. Поскольку у нас нет невстроенных функций, то создавать файл IntArrayRC.C не нужно.

Вот пример простой программы, использующей классы IntArray и IntArrayRC:

Нам нужно передать параметры ia и 8 конструктору базового класса IntArray. Для этого служит специальная синтаксическая конструкция. Вот как выглядят реализации



#include <iostream> #include IntArray.h #include IntArrayRC.h

void swap( IntArray &ia, int ix, int jx ) {

int tmp = ia[ ix ]; ia[ ix ] = ia[ jx ]; ia[ jx ] = tmp;

int main() {

int array[ 4 ] = { 0, 1, 2, 3 }; IntAArray ia1 ( array, 4 ) ;

IntArrayRC ia2( array, 4 );

ошибка: должно быть size-1 не может быть выявлена объектом IntArray cout << swap() with IntArray ia1 << endl; swap( ia1, 1, ia1.size() );

правильно: объект IntArrayRC поймает ошибку cout << swap() with IntArrayRC ia2 << endl; swap( ia2, 1, ia2.size() ); return 0;

При выполнении программа выдаст следующий результат:

swap() with IntArray ia1 swap() with IntArrayRC ia2 Assertion failed: ix >= 0 && ix < size, file IntArrayRC.h, line 19

Упражнение 2.8

Отношение наследования между типом и подтипом служит примером отношения является. Так, массив IntArrayRC является подвидом массива IntArray, книга является подвидом выдаваемых библиотекой предметов, аудиокнига является подвидом книги и

(a) функция-член является подвидом функции

(b) функция-член является подвидом класса

(c) конструктор является подвидом функции-члена

(d) самолет является подвидом транспортного средства

(e) машина является подвидом грузовика

(f) круг является подвидом геометрической фигуры

(g) квадрат является подвидом треугольника

(h) автомобиль является подвидом самолета

т.д. Какие из следующих утверждений верны?

(i) читатель является подвидом библиотеки



1 ... 14 15 16 [ 17 ] 18 19 20 ... 395

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