Бьерн Страуструп - Язык программирования С++. Главы 5-8
Страница 6. Инициализация



5.2.4 Инициализация

 Инициализация объектов класса с помощью таких функций как set_date()
 - неэлегантное и чреватое ошибками решение. Поскольку явно не было
 указано, что объект требует инициализации, программист может либо забыть
 это сделать, либо сделать дважды, что может привести к столь же
 катастрофическим последствиям. Лучше дать программисту возможность
 описать функцию, явно предназначенную для инициализации объектов.
 Поскольку такая функция конструирует значение данного типа, она
 называется конструктором. Эту функцию легко распознать - она имеет
 то же имя, что и ее класс:

            class date {
               // ...
               date(int, int, int);
            };

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

            date today = date(23,6,1983);
            date xmas(25,12,0);  // краткая форма
            date my_birthday;    // неправильно, нужен инициализатор

    Часто бывает удобно указать несколько способов инициализации
 объекта. Для этого нужно описать несколько конструкторов:

            class date {
               int month, day, year;
            public:
               // ...
               date(int, int, int);  // день, месяц, год
               date(int, int);       // день, месяц и текущий год
               date(int);            // день и текущие год и месяц
               date();               // стандартное значение: текущая дата
               date(const char*);    // дата в строковом представлении
            };

 Параметры конструкторов подчиняются тем же правилам о типах
 параметров, что и все остальные функции ($$4.6.6). Пока конструкторы
 достаточно различаются по типам своих параметров, транслятор
 способен правильно выбрать конструктор:

               date today(4);
               date july4("July 4, 1983");
               date guy("5 Nov");
               date now;       // инициализация стандартным значением

    Размножение конструкторов в примере c date типично. При разработке
 класса всегда есть соблазн добавить еще одну возможность, - а вдруг
 она кому-нибудь пригодится. Чтобы определить действительно нужные
 возможности, надо поразмышлять, но зато в результате, как правило,
 получается более компактная и понятная программа. Сократить число
 сходных функций можно с помощью стандартного значения параметра.
 В примере с date для каждого параметра можно задать стандартное
 значение, что означает: "взять значение из текущей даты".

               class date {
                 int month, day, year;
               public:
                 // ...
                 date(int d =0, int m =0, y=0);
                 // ...
               };

               date::date(int d, int m, int y)
               {
                 day = d ? d : today.day;
                 month = m ? m : today.month;
                 year = y ? y : today.year;
                 // проверка правильности даты
                 // ...
               }

     Когда используется стандартное значение параметра, оно должно
 отличаться от всех допустимых значений параметра. В случае месяца и
 дня очевидно, что при значении нуль - это так, но неочевидно,
 что нуль подходит для значения года. К счастью, в европейском
 календаре нет нулевого года, т.к. сразу после 1 г. до р.х.
 (year==-1) идет 1 г. р.х. (year==1). Однако для обычной программы
 это, возможно, слишком тонкий момент.
     Объект класса без конструктора может инициализироваться
 присваиванием ему другого объекта этого же класса. Это незапрещено и
 в том случае, когда конструкторы описаны:

            date d = today;  // инициализация присваиванием

 На самом деле, имеется стандартный конструктор копирования,
 определенный как поэлементное копирование объектов одного класса.
 Если такой конструктор для класса X не нужен, можно переопределить
 его как конструктор копирования X::X(const X&). Подробнее поговорим
 об этом в $$7.6.

 
« Предыдущая статья   Следующая статья »