|
Программирование >> Инициализация объектов класса, структура
IntArray::IntArray (int sz) инициазация членов данн1х size = sz; ia = new int[ size]; инициализация элементов массива for (int ix=0; ix< size; ++ix) ia[ix] = 0; Вот как может выглядеть определение нашего конструктора по умолчанию: Это определение содержит несколько упрощенный вариант реализации. Мы не позаботились о том, чтобы попытаться избежать возможных ошибок во время выполнения. Какие ошибки возможны? Во-первых, оператор new может потерпеть неудачу при выделении нужной памяти: в реальной жизни память не бесконечна. (В разделе 2.6 м1 увидим, как обрабатываются подобные ситуации.) А во-вторых, параметр sz из-за небрежности программиста может иметь некорректное значение, например нуль или отрицательное. Что необычного мы видим в таком определении конструктора? Сразу бросается в глаза первая строчка, в которой использована операция разрешения области видимости (): IntArray::IntArray(int sz); Дело в том, что мы определяем нашу функцию-член (в данном случае конструктор) вне тела класса. Для того чтобы показать, что эта функция на самом деле является членом класса IntArray, мы должны явно предварить имя функции именем класса и двойным двоеточием. (Подробно области видимости разбираются в главе 8; области видимости применительно к классам рассматриваются в разделе 13.9.) Второй конструктор класса IntArray инициализирует объект IntArray значениями элементов массива встроенного типа. Он требует двух параметров: массива встроенного типа со значениями для инициализации и размера этого массива. Вот как может int ia[10] = {0,1,2,3,4,5,6,7,8,9}; выглядеть создание объекта IntArray с использованием данного конструктора: IntArray iA3(ia,10); IntArray array1(1024); то значение 1024 будет передано в конструктор. Если же размер не задан, допустим: IntArray array2; то в качестве значения отсутствующего параметра конструктор принимает величину DefaultArraySize. (Не будем пока обсуждать использование ключевого слова static в определении члена DefaultArraySize: об этом говорится в разделе 13.5. Скажем лишь, что такой член данных существует в единственном экземпляре и принадлежит одновременно всем объектам данного класса.) IntA\rray::IntA\rray (const IntAArray &rhs ) обработки ошибок: инициализация членов данных rhs. size; size = ia = new int[ size]; инициализация элементов массива for (int ix=0; ix< size; ++ix) ia[ix] = rhs.ia[ix]; В этом примере мы видим еще один составной тип данных - ссылку на объект, которая обозначается символом &. Ссылку можно рассматривать как разновидность указателя: она также позволяет косвенно обращаться к объекту. Однако синтаксис их использования различается: для доступа к члену объекта, на который у нас есть ссылка, следует использовать точку, а не стрелку; следовательно, мы пишем rhs. size, а не rhs-> size. (Ссылки рассматриваются в разделе 3.6.) Заметим, что реализация всех трех конструкторов очень похожа. Если один и тот же код повторяется в разных местах, желательно вынести его в отдельную функцию. Это облегчает и дальнейшую модификацию кода, и чтение программы. Вот как можно модернизировать наши конструкторы, если выделить повторяющийся код в отдельную функцию init() : Реализация второго конструктора очень мало отличается от реализации конструктора по IntA\rray::IntA\rray (int *array, int sz) инициализация членов данных size = sz; ia = new int[ size]; инициазация элементов массива for (int ix=0; ix< size; ++ix) ia[ix] = array[ix]; умолчанию. (Как и в первом случае, мы пока опустили обработку ошибочных ситуаций.) Третий конструктор называется копирующим конструктором. Он инициализирует один объект типа IntArray значением другого объекта IntArray. Такой конструктор вызывается автоматически при выполнении следующих инструкций: IntArray array; следящие два объявления совершенно эквивалентных: IntAArray ia1 = array; IntArray ia2 (array); Вот как выглядит реализация копирующего конструктора для IntArray, опять-таки без class IntArray { public: explicit IntArray (int sz = DefaultAArraySize); IntAArray (int *array, int array size) ; IntArray (const IntArray &rhs); ... private: void init (int sz,int *array); ... функция, используемая всеми конструкторами void IntA\rray::init (int sz,int *array) { size = sz; ia = new int[ size]; for (int ix=0; ix< size; ++ix) if ( !array ) ia[ix] = 0; else ix[ix] = array[ix]; модифицированнхе конструкторы IntArray::IntArray (int sz) { init(sz,0); } IntA\rray::IntA\rray (int *array, int array size) { init (array size,array); } IntArray::IntArray (const IntArray &rhs) { init (rhs. size,rhs.ia); } Имеется еще одна специальная функция-член - деструктор, который автоматически вызывается в тот момент, когда объект прекращает существование. Имя деструктора совпадает с именем класса, только в начале идет символ тильда: (~). Основное назначение данной функции - освободить ресурсы, отведенные объекту во время его создания и использования. Применение деструкторов помогает бороться с трудно обнаруживаемыми ошибками, ведущими к утечке памяти и других ресурсов. В случае класса IntArray эта функция-член должна освободить память, выделенную в момент создания объекта. (Подробно конструкторы и деструкторы описаны в главе 14.) Вот как выглядит class IntArray { деструктор для IntArray: public: конструкторы explicit IntArray (int sz = DefaultAArraySize); IntAArray (int *array, int array s IntArray (const IntArray &rhs); деструктор ~IntArray() { delete[] ia; } ... private: ...
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |