Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
63
Добавлен:
16.02.2016
Размер:
455 Кб
Скачать

Конструкторы по умолчанию и конструкторы копирования

C++ определяет два специальных вида конструкторов: конст­руктор по умолчанию, о котором мы упоминали выше, и конст­руктор копирования. Конструктор по умолчанию не имеет пара­метров (или все его параметры должны иметь значения по умол­чанию) и вызывается при создании объекта, которому не заданы аргументы. Следует избегать двусмысленности при вызове кон­структоров. В приведенном ниже примере два конструктора по умолчанию являются двусмысленными:

class Т

{

public:

//Конструктор по умолчанию

Т();

//Конструктор c одним параметром;

//может быть использовал как конструктор по умолчанию

Т (int I=0);

};

int main ()

{

Т ob1(10) ;//Использует Т:: Т (int)

Т оb2; //Не верно; неоднозначность вызова. Т: :Т() или Т:: Т (int =0)

return 0;

}

В данном случае, чтобы устранить неоднозначность, доста­точно удалить из объявления класса конструктор по умолчанию.

Конструктор копирования (или конструктор копии) создает объект класса, копируя при этом данные из уже существующего объекта данного класса. В связи с этим он имеет в качестве един­ственного параметра константную ссылку на объект класса (const T&) или просто ссылку на объект класса (T&). Использо­вание первого предпочтительнее, так как последний не позволяет копировать константные объекты. Приведем пример использова­ния конструктора копирования:

class Coord

{

int x, y;

public:

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

Coord(const Coord& src);

};

Coord::Coord(const Coord& src)

{

x = src.x;

у = src.у;

}

int main()

{

Coord ob1(2,9);

Coord ob2 = ob1;

Coord ob3(obl);

//...

return 0;

}

Ссылка передается всякий раз, когда новый объект инициа­лизируется значениями существующего. Если вы не преду­смотрели конструктор копирования, компилятор генерирует конструктор копирования по умолчанию. В C++ различают поверхностное и глубинное копирование данных. При поверх­ностном копировании происходит передача только адреса от одной переменной к другой, в результате чего оба объекта ука­зывают на одни и те же ячейки памяти. В случае глубинного копирования происходит действительное копирование значе­ний всех переменных из одной области памяти в другую. Кон­структор копирования по умолчанию, созданный компилято­ром, создает буквальную (или побитную) копию объекта, то есть осуществляет поверхностное копирование. Полученная копия объекта скорее всего будет непригодной, если она со­держит указатели или ссылки. Действительно, если эти указа­тели или ссылки ссылаются на динамически распределенные объекты или на объекты, встроенные в копируемый объект, они будут недоступны в созданной копии объекта. Поэтому для классов, содержащих указатели и ссылки, следует вклю­чать в определение класса конструктор копирования, который будет осуществлять глубинное копирование, не полагаясь на создаваемый компилятором конструктор копирования по умолчанию. В этом конструкторе, как правило, выполняется копирование динамических структур данных, на которые ука­зывают или на которые ссылаются члены класса. Класс дол­жен содержать конструктор копирования, если он перегружает оператор присваивания.

Если в классе не определен конструктор, компилятор пытает­ся сгенерировать собственный конструктор по умолчанию и, если нужно, собственный конструктор копирования. Эти сгенериро­ванные компилятором конструкторы рассматриваются как от­крытые функции-члены. Подчеркнем, что компилятор генерирует эти конструкторы, если в классе не определен никакой другой конструктор.

Сгенерированный компилятором конструктор по умолчанию создает объект и вызывает конструкторы по умолчанию для базо­вых классов и членов-данных, но не предпринимает никаких дру­гих действий. Конструкторы базового класса и членов-данных вызываются, только если они существуют, доступны и являются недвусмысленными. Когда конструируется объект производного класса, конструирование начинается с объектов его базовых классов и продвигается вниз по иерархии классов, пока не будет создан заданный объект. Подробнее этот вопрос будет рассмот­рен в следующей главе.

Сгенерированный компилятором конструктор копирования создает новый объект и выполняет почленное копирование со­держимого исходного объекта. Если существуют конструкторы базового класса или члена-класса, — они вызываются; иначе вы­полняется побитное копирование. Если все базовые классы и классы членов-данных класса имеют конструкторы копирования, которые воспринимают const-аргумент, то сгенерированный ком­пилятором конструктор копирования воспринимает аргумент типа const T&. В противном случае он воспринимает аргумент типа Т& (без const).

Соседние файлы в папке ЯзыкС++Глушаков