Конструктор копирования

. . .

};

//--------------------------

monstr::monstr(int he, int am){

health = he; ammo = am; skin = red; name = 0;

}

//--------------------------

monstr::monstr(color sk){

switch (sk){

case red: health=100; ammo =10; skin = red; name = 0; break;

case green: health=100; ammo =20; skin = green; name = 0; break;

case blue: health=100; ammo =40; skin = blue; name = 0; break;

}

}

//--------------------------

monstr::monstr(char * nam){

name = new char [strlen(nam) + 1];

// К длине строки добавляется 1 для хранения нуль-символа

Strcpy (name, nam);

health = 100; ammo =10; skin = red;

}

//--------------------------

monstr * m = new monstr ("Ork");

monstr Green (green);

Первыйиз приведенных выше конструкторов является конструктором по умолчанию, поскольку его можно вызвать без параметров. Объекты класса monstr теперь можно инициализировать различными способами, требуемый конструктор будет вызван в зависимости от списка значений в скобках. При задании нескольких конструкторов следует соблюдать те же правила, что и при написании перегруженных функций — у компилятора должна быть возможность распознать нужный вариант.

ПРИМЕЧАНИЕ ----------------------------------------------------

Перегружать можно не только конструкторы, но и другие методы класса.

-----

Существует еще один способ инициализации полей в конструкторе (кроме использованного в приведенной выше программе присваивания полям значений формальных параметров) — с помощью списка инициализаторов, расположенных после двоеточия между заголовком и телом конструктора:

monstr::monstr(in the, int am):

health (he), ammo (am), skin (red), name (0){}

 

Поля перечисляются через запятую.

Для каждого поля в скобках указывается инициализирующее значение, которое может быть выражением.

Без этого способа не обойтись приинициализации

· полей-констант,

· полей-ссылок и

· полей-объектов.

В последнем случае будет вызван конструктор, соответствующий указанным в скобках параметрам.

ПРИМЕЧАНИЕ-------------------------------------------------------------

Конструктор не может возвратить значение, чтобы сообщить об ошибке во время инициализации. Для этого можно использовать механизм обработки исключительных ситуаций (см. раздел «Исключения в конструкторах и деструкторах», с. 228).


Конструктор копирования — это специальный вид конструктора, получающий в качестве единственного параметра указатель на объект этого же класса:

T::T(const T&) { .../* Тело конструктора */}

где Т — имя класса.

Этот конструктор вызывается в тех случаях, когда новый объект создается путем копирования существующего:

· при описании нового объекта с инициализацией другим объектом;

· при передаче объекта в функцию по значению;

· при возврате объекта из функции (а также при обработке исключений).

Если программист не указал ни одного конструктора копирования, компилятор создает его автоматически.

Такой конструктор выполняет поэлементное копирование полей.

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

Запишем конструктор копирования для класса monstr.

Поскольку в нем есть поле name, содержащее указатель на строку символов, конструктор копирования должен выделять память под новую строку и копировать в нее исходную:

monstr::monstr(const monstr &M){

if (M.name){

name = new char [strlen(M.name) + 1];

strcpy(name, M.name);}

else name = 0;

health = M.health; ammo = M.ammo; skin = M.skin;

}