И.А. Волкова, А.В. Иванов, Л.Е. Карпов - Основы объектно-ориентированного программирования. Язык программирования С++ (1114893), страница 5
Текст из файла (страница 5)
в этом случае при описании соответствующей функции указывается специальный тип возвращаемого значения void.В описании конструктора тип возвращаемого значения не указываетсяне потому, что возвращаемого значения нет. Оно как раз есть. Ведь результатом работы конструктора в соответствии с его названием является созданный объект того типа, который описывается данным классом. Страуструп отмечал, что конструктор — это то, что область памяти превращаетв объект.Конструкторы можно классифицировать разными способами:1) по наличию параметров:27Конструкторы и деструкторыбез параметров,— с параметрами;—2) по количеству и типу параметров:— конструктор умолчания,— конструктор преобразования,— конструктор копирования,— конструктор с двумя и более параметрами.Набор и типы параметров зависят от того, на основе каких данныхсоздается объект.В классе может быть несколько конструкторов.
в соответствиис правилами языка С++ все они имеют одно имя, совпадающее с именемкласса, что является одним из проявлений статического полиморфизма.Компилятор выбирает тот конструктор, который в зависимости от ситуации,в которой происходит создание объекта, удовлетворяет ей по количествуи типам параметров. Естественным ограничением является то, что в классе неможет быть двух конструкторов с одинаковым набором параметров.Деструкторы применяются для корректного уничтожения объектов.Часто процесс уничтожения объектов включает в себя действия по освобождению выделенной для них по операциям new памяти.Имя деструктора: ~имя_классаУ деструкторов нет параметров и возвращаемого значения.В отличие от конструкторов деструктор в классе может быть толькоодин.Пример:Описание класса.class box{int len, wid, hei;public:box ( int l, int w, int h ){len = l; wid = w; hei = h;}box(int s){len = wid = hei = s;}box(){len = 2; wid = hei = 1;}int volume(){return len * wid * hei;}};28Конструкторы и деструкторы4.1.
Конструктор умолчанияКонструктор без параметров называется конструктором умолчания. Еслидля создания объекта не требуется каких-либо параметров, то используетсяконструктор умолчания. При описании таких объектов после имени классауказывается только идентификатор переменной:class Х { … };Х x1;ЗамечаниеРоль конструктора умолчания может играть конструктор, у которого все параметры имеют априорные значения, например:box (int l = 24, int w = 12, int h = 6);4.2.
Конструктор преобразованияи конструкторы с двумяи более параметрамиЕсли для создания объекта необходимы параметры, то они указываютсяв круглых скобках после идентификатора переменной:box b2(1,2,3);box b3(5);Указываемые параметры являются параметрами конструктора класса.Если у конструктора имеется ровно один входной параметр, который непредставляет собой ссылку на свой собственный класс, то соответствующийконструктор называется конструктором преобразования. Этот конструкторназывается так в связи с тем, что в результате его работы на основе объектаодного типа создается объект другого типа (типа описываемого класса).Если уже описан класс T и описывается новый класс X, то его конструкторы преобразования могут иметь любой из следующих прототипов:X(T);X(T&);X(const T&);Последний прототип служит для защиты от изменения передаваемогофактического параметра в теле конструктора, так как при получении ссылкина фактический параметр используется собственно передаваемый объект, ане его локальная копия.29Конструкторы и деструкторыПримечаниеВыделение в отдельную группу конструкторов с двумя и более параметрами,независимо от их типа, является в некотором смысле, условным.
Так, например, если есть два класса: Vector и Matrix, то для создания соответствующих объектов:Vector v1(10);Matrix m1(10,15);используется в первом случае один параметр, а во втором случае — два параметра. Таким образом, в первом случае объект создается с помощью конструктора преобразования, а во втором случае, с формальной точки зрения, спомощью конструктора с двумя параметрами, хотя в обоих случаях фактическивыполняется одна и та же процедура: создание объекта на основе заданныхчисловых параметров.Как уже было отмечено, если у параметра конструктора преобразованияимеется априорное значение, и при описании объекта явно не задается фактический параметр, этот конструктор играет роль конструктора умолчания.Пример:class X{int x1;public:X(int px1 = 0}};Для такого класса будут верны следующие объявления объектов:int main(){… Х x1, x2(1); …}4.3. Конструктор копированияПри создании объекта его информационные члены могут быть проинициализированы значениями полей другого объекта этого же типа, то есть объектсоздается как копия другого объекта.Для такого создания объекта используется конструктор копирования.Инициализация может быть выполнена аналогично инициализациипеременных встроенных типов с использованием операции присваиваниясовместно с объявлением объекта:box b5(2,4,6); // создание объекта типа box с// использованием числовых данныхbox b6 = b5;// создание объекта b6 — копии объекта b530Конструкторы и деструкторыЕсли инициализация производится объектом такого же типа, то объект-инициализатор также может быть указан в круглых скобках после идентификатора создаваемого объекта:box b7(b5);Свод ситуаций, в которых используется конструктор копирования,описаны ниже.Если класс не предусматривает создания внутренних динамическихструктур, например, массивов, создаваемых с использованием операции new,то в конструкторе копирования достаточно предусмотреть поверхностноекопирование, то есть почленное копирование информационных членовкласса.Конструктор копирования, осуществляющий поверхностное копирование, можно явно не описывать, он сгенерируется автоматически.Если же в классе предусмотрено создание внутренних динамическихструктур, использование только поверхностного копирования будет ошибочным, так как информационные члены-указатели, находящиеся в разныхобъектах, будут иметь одинаковые значения и указывать на одну и ту жеразмещенную в динамической памяти структуру.
Автоматически сгенерированный конструктора копирования в данном классе не позволит корректносоздавать объекты такого типа на основе других объектов этого же типа.В подобных случаях необходимо глубокое копирование, осуществляющее не только копирование информационных членов объекта, но и самихдинамических структур. При этом, естественно, информационные члены-указатели в создаваемом объекте должны не механически копироватьсяиз объекта-инициализатора, а указывать на вновь созданные динамическиеструктуры нового объекта.Пример:Для класса stack конструктор копирования может быть определен следующим образом:class stack{char* c1;inttop, size;public:stack ( int n = 10 ){size = n;top = 0;c1= new char[size];}stack(stack & s1);. .
.};stack::stack ( stack & s1 ){size = s1.size;top = s1.top;c1= new char[size];31Конструкторы и деструкторыfor ( int i = 0; i < size; ++I )c1[i] = s1.c1[i];}Замечания по работе конструктора копирования:1. Входной параметр является внешним объектом по отношению ксоздаваемому объекту. Тем не менее, имеется возможность прямогообращения к закрытым членам этого внешнего объекта.
Это возможно только потому, что входной параметр имеет тип, совпадающий с типом создаваемого в результате работы конструкторакопирования объекта. Если бы на вход конструктора поступал быобъект другого типа (например, в конструкторе преобразованиякласса vector входным параметром был бы объект, созданный наоснове класса matrix), то для доступа к закрытым членам объекта-параметра необходимо было бы применять специальные средства.
Это связано с тем, что единицей защиты является не объект, атип, то есть методы объекта могут обращаться к закрытым членамне только данного объекта, но и к закрытым членам любого объектаданного типа.2. В момент описания конструктора копирования класс, как тип данных, еще не описан до конца. Тем не менее, идентификатор классауже используется в качестве полноценного типа данных при описании входного параметра конструктора копирования. Такая технология схожа с описанием рекурсивной функции, когда телоописываемой функции содержит вызов этой же функции.В отличие от конструктора преобразования, входной параметр конструктора копирования имеет тип, описываемый данным классом.
Таким образом, если описывается класс Х, то его конструктор копирования можетиметь один из следующих прототипов:Х(Х&);Х(const Х&);Объект, создаваемый с использованием конструктора копирования,может инициализироваться не только именованными объектами, нои временно созданными объектами.Пример:/* Явный запуск конструктора с тремя параметрами. Адресдинамически созданного объекта типа box присваиваетсяпеременной b4. */box* b4 = new box(2,3,5);/* Разыменование указателя на объект, т.е. получениедоступа к информации, хранящейся в нем, и использование еедля инициализации создаваемого объекта.
*/box b5 = * b4;// Создание временного объекта и инициализацияименованного объекта.32Конструкторы и деструкторыbox b6 = box(4,7,1);4.4. Спецификатор «explicit»Если инициализация создаваемого объекта производится объектом другоготипа, то автоматически производится вызов соответствующего конструктора преобразования для преобразования инициализирующего значения ктипу объявленного объекта.Например, для приведенного выше класса stack описание объектакласса с инициализацией может быть таким:stack st1 = 15оно эквивалентно следующему:stack st1 = stack(15)Таким образом, если пользователь класса stack предполагал создатьобъект st1 типа stack с максимальной глубиной, задаваемой по умолчанию (10элементов), и поместить в его вершину значение 15, то он ошибся, посколькуреальным результатом сделанного объявления будет создание пустого стекас максимальной глубиной в 15 элементов.Для подавления неявного вызова конструктора преобразования, еслитакое действие может привести к ошибке, конструктор преобразования необходимо объявлять с использованием ключевого слова explicit (явный):explicit stack ( int n = 10 ) {.