Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Cpp_Страуструп.doc
Скачиваний:
16
Добавлен:
03.05.2015
Размер:
3.2 Mб
Скачать

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.