И.А. Волкова, А.В. Иванов, Л.Е. Карпов - Основы объектно-ориентированного программирования. Язык программирования С++ (ЧБ) (1114895), страница 7
Текст из файла (страница 7)
В случае использования списка инициализации тело конструктораможет оказаться пустым. Но и в этом виде оно обязательно должно присутствовать.Пример:class Z0{int z01;public:Z0(){z01 = 0;30}Z0(int pz0){z01 = pz0;}};class Point{int x, y;public:Point(): x(0), y(0){}Point(int x1, const int y1): x(x1), y(y1){}Point(const point& p1) : x(p1.x), y(p1.y){}};class Z1{Point p, p2, p3;int z;public:Z1(int z2, int x2, int y2, int pz01):p2(x2,y2), p(pz01,0), p3(p2), z(z2){}};int main(){z1* z3 = new z1(1,2,3,4);return 0;}Недопустимо использование конструкторов с параметрами (даже константами) при описании подобъектов классов (членов-данных, являющихся объектами других классов). Если подобъект класса необходимо инициализировать сиспользованием констант, то это можно сделать только в строке инициализации.Так, класс Z1 из приведенного только что примера не может быть описан следующим образом:class z1{point p;point p2(2,3); // ОШИБКА!point p3;int z;public:z1(int z2): p3(p2),z(z2){}};Правильное описание класса:class z1{point p, p2, p3;int z;public:z1(int z2): p2(2,3),p3(p2),z(z2){}};31Если бы в классе z1 были описаны несколько конструкторов, то в строкуинициализации каждого из них необходимо было бы поместить вызов конструктора с двумя и более параметрами для поля p2.4.8.Порядок вызова конструкторов и деструкторовИтак, конструкторы можно классифицировать по набору входных параметров следующим образом:1) x()– конструктор умолчания2) x(x&), x(const x&)– конструктор копирования3) x(t), x(t&), x(const t&) – конструктор преобразования4) конструктор с двумя и более параметрамиВ классе может быть описано несколько конструкторов преобразования иконструкторов с двумя и более параметрами.
Единственное требование к ним: неможет быть двух конструкторов с одинаковым (по типам) набором параметров, вчастности, не может быть двух конструкторов умолчания.При создании объекта конструкторы вызываются в следующем порядке:1) Конструкторы базовых классов, если класс для создаваемого объектаявляется наследником других классов в порядке их появления в описании класса. Если в списке инициализации описываемого класса присутствует вызов конструктора преобразования (или конструктора с двумя иболее параметрами) базового класса, то вызывается конструктор преобразования (или конструктор с двумя и более параметрами), иначе вызывается конструктор умолчания базового класса.2) Конструкторы умолчания всех вложенных информационных членов,которые не перечислены в списке инициализации, и конструкторы преобразования, копирования и конструкторы с двумя и более параметрамивсех вложенных информационных членов, которые перечислены в списке инициализации.
Все перечисленные в данном пункте конструкторы(умолчания, преобразования, копирования, с двумя и более параметрами) вызываются в порядке описания соответствующих информационныхчленов в классе.3) Собственный конструктор.Такая последовательность вызова конструкторов логически обосновываетсятем, что в момент выполнения собственного конструктора все информационныеполя должны быть уже проинициализированы.Деструкторы вызываются в обратном порядке:1) Собственный деструктор.
В момент начала его работы поля класса ещене очищены, и их значения могут быть использованы в теле деструктора.2) Деструкторы вложенных объектов в порядке, обратном порядку ихописания.3) Деструкторы базовых классов в обратном порядке их задания.32Свод ситуаций, при которых вызываются конструкторы и деструкторыОбычный конструктор (не копирования) вызывается:1) при создании объекта ( при обработке описания объекта);2) при создании объекта в динамической памяти (с использованием операции new). При этом в динамической памяти предварительно отводитсянеобходимый по объему фрагмент памяти;3) при композиции объектов;4) при создании объекта производного класса.Замечание.
Если в программе создается не единичный (скалярный) объект, амассив объектов, то в соответствующем классе (структуре) должен быть конструктор умолчания (явно или неявно сгенерированный). Действительно, при объявлении массива объектов или создании массива в динамической памяти указывается размерность массива, что несовместимо с заданием параметров для конструктора преобразования или конструктора с двумя и более параметрами:class X{ .
. .};X* x1 = new X[10];Как уже было указано, если в классе явно описан хотя бы один конструктор,то конструктор умолчания не генерируется системой неявно. Для удаления такогомассива должна применяться векторная форма операции delete, при использовании которой деструктор вызывается для каждого элемента массива:delete[] x1;Конструктор копирования вызывается:1) при инициализации создаваемого объекта:box a(1,2,3);box b = a;// вызов конструктора с тремя параметрами// инициализация2) при инициализации временным объектом:box c = box(3,4,5);3) при передаче параметров-объектов в функцию по значению:int f(box b);4) при возвращении результата работы функции в виде объекта.box f ();Примечание 1.
Если используется оптимизирующий компилятор, то при обработке инициализации вида:box c = box(3,4,5)временный объект не создается, и вместо конструктора копирования используется кон-33структор с тремя параметрами:(box c(3,4,5)).Примечание 2. Если при возвращении результата работы функции в виде объектатип возвращаемого значения не совпадает с типом результата работы функции, то вызывается не конструктор копирования, а конструктор преобразования или функцияпреобразования ( описывается ниже). Данное преобразование выполняется, если онооднозначно. Иначе фиксируется ошибка.Пример:class Y;class X{. .
.public:X(const Y& y1);. . .};class Y{. . .public:. . .X f(){. . .return *this;}};X::X(const Y& y1){. . .}Деструктор вызывается:1) при свертке стека – при выходе из блока описания объекта, в частности,при обработке исключений (при выходе из try-блока по операторуthrow, try-блоки описываются далее), завершении работы функций;2) при уничтожении временных объектов – сразу, как только завершитсяконструкция, в которой они использовались;3) при выполнении операции delete для указателя, получившего значениев результате выполнения операции new. После выполнения деструктораосвобождается выделенный для объекта участок памяти;4) при завершении работы программы при уничтожении глобальных истатических объектов.Примечание. Все правила описания и использования конструкторов и деструкторов применимы и для структур.345.Статические члены классаИнформационные члены класса, которые могут быть представлены в единственном экземпляре для всех объектов данного типа, в случае такого представления называются статическими членами.
Они не являются частью объектов этогокласса и размещаются в статической памяти. Для их описания используетсяслужебное слово static.Для всех объектов, созданных на основе класса, содержащего статическийчлен, существует только одна копия этого члена. Примером такого статическогочлена является счетчик числа созданных объектов данного класса. Такой счетчикможет существовать только в отрыве от всех экземпляров объектов данногокласса, в то же время работать с ним обычно приходится одновременно с вызовомобычных методов, например, конструкторов объектов, поэтому описывать счетчик удобнее именно как элемент класса.Статическими могут быть не только информационные члены класса, но и егометоды. Статический метод не может использовать никакие нестатические членыкласса, так как, являясь частью класса, а не объекта, он не имеет неявного параметра this.
Поскольку статический метод не использует специфического содержимого конкретного объекта, то обращение к нему может осуществляться нетолько с использованием идентификатора объекта, но и с использованием идентификатора класса:имя_класса :: имя_функции (фактические_параметры);Одно из очевидных применений статических методов – манипуляция глобальными объектами и статическими полями данных соответствующего класса.Примечание 1. Статические методы класса не могут вызывать нестатические, таккак последние имеют доступ к данным конкретных объектов. Обратное допустимо: нестатические методы могут вызывать статические методы.Примечание 2.
Статический метод класса может создавать объекты данного илюбого другого класса. Это можно использовать, в частности, если необходимо в программе запретить создание объектов простым объявлением или с использованием операции new. В этом случае конструктор и деструктор помещаются в закрытую областькласса, а для создания и уничтожения объекта используются специальные статическиеметоды, которые можно вызывать, не имея ни одного объекта.Примечание 3. Статические методы класса не могут быть виртуальными и константными (inline–функциями быть могут).Пример:#include <iostream>using namespace std;class X{X(){}~X(){}public:static X& createX(){35X* x1 = new X;cout << "X created" << endl;return *x1;}static void destroyX(X& x1){delete &x1;cout << "X destroyed" << endl;}};int main(){X& xx1 = X::createX();.
. .X::destroyX(xx1);return 0;}Статические информационные члены класса, даже находящиеся в закрытойобласти (а это характерно для информационных членов класса в соответствии спринципом инкапсуляции), необходимо объявить дополнительно вне класса (свозможной инициализацией):тип_переменной имя_класса :: идентификатор = инициализатор;Это связано с тем, что память для статического объекта должна быть выделена до начала работы программы. В то же время при обработке описания классадо создания конкретных объектов никакие области памяти не отводятся. В дальнейшем прямое обращение к статическим информационным членам, находящимся в закрытой секции, недопустимо. Если инициализация не нужна, то всеравно необходимо дополнительное объявление статического члена вне класса длярезервирования памяти для статического члена. В противном случае на этапесборки исполняемого модуля будет выдана ошибка о неразрешенной внешнейссылке.Пример:class B {static int i;};// статический информационный член// классаpublic:static void f(int j){ // статический методi = j;}int B::I = 10;////////дополнительное внешнее определениестатической переменной синициализацией статическогоинформационного члена класса b.36int main(){B a;.
. .B::f(1);. . .return 0;}6.// вызов статической функции-члена класса.Константные члены класса. Модификатор constВсе информационные члены класса, не являющиеся статическими информационными членами, можно представлять, как данные, доступные методу классачерез указатель this (в случае необходимости этот указатель можно употреблятьявно).Если необходимо запретить методу изменять информационные члены объектов класса, то при его описании используется дополнительный модификаторconst:Тип_возвра щаемогоИмяформальные(параметры ) const { тело _ функции }функциизначенияОписанные таким образом методы класса называются константными.Тем не менее, статические члены класса могут изменяться такой функцией,так как они являются частью класса, но не объекта.