русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

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


Дата добавления: 2013-12-23; просмотров: 1570; Нарушение авторских прав


Присваивание объектов

Возвращение объектов функциями

Функция может возвращать объект в точку вызова. В качестве примера рассмотрим программу:

#include <iostream.h>

class myclass

{

int i;

public:

void set_i(int n) { i=n; }

int get_i() {return i;}

};

myclass f(); // возвращение объекта типа myclass

int main()

{

myclass c1;

c1 = f();

cout << c1.get_i() << "\n";

return 0;

}

myclass f()

{

myclass x;

x.set_i(1);

return x;

}

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

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

#include <iostream.h>

class myclass

{

int i;

public:

void set_i(int n) { i=n; }

int get_i() { return i; }

};

int main()

{

myclass ob1, ob2;

ob1.set_i(99);

ob2 = ob1; // присвоение данных ob1 объекту ob2

cout << "this is ob2's i: " << ob2. get_i();



return 0;

}

По умолчанию все данные одного объекта присваиваются другому путем побитового копиро­вания. Однако возможно перегрузить оператор присваивания и определить некоторые другие процедуры присваивания.

По умолчанию при инициализации одного объекта другим C++ выполняет побитовое копирова­ние. Это означает, что точная копия инициализирующего объекта создается в целевом объекте. Хотя в большинстве случаев такой способ инициализации объекта является вполне приемлемым, имеются случаи, когда побитовое копирование не может использоваться. Например, такая ситу­ация имеет место, когда объект выделяет память при своем создании. Рассмотрим в качестве при­мера два объекта А и Вкласса ClassType, выделяющего память при создании объекта. Положим, что объект Ауже существует. Это означает, что объект Ауже выделил память. Далее предполо­жим, что Аиспользовался для инициализации объекта В,как показано ниже:

ClassType В = А;

Если в данном случае используется побитовое копирование, то В станет точной копией А. Это означает, что В будет использовать тот же самый участок выделенной памяти, что и А, вместо того, чтобы выделить свой собственный. Ясно, что такая ситуация нежелательна. Например, если класс ClassType включает в себя деструктор, освобождающий память, то тогда одна и та же па­мять будет освобождаться дважды при уничтожении объектов А и В.

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

Для решения подобных проблем язык C++ позволяет создать конструктор копирования, кото­рый используется компилятором, когда один объект инициализирует другой. При наличии кон­структора копирования побитовое копирование не выполняется. Общая форма конструктора ко­пирования имеет вид:

имя_класса(const имя_класса &оbj)

{

тело конструктора

}

Здесь obj является ссылкой на объект в правой части инициализации. Конструктор копирования может иметь также дополнительные параметры, если для них определены значения по умолча­нию. Однако в любом случае первым параметром должна быть ссылка на объект, выполняющий инициализацию.

Инициализация возникает в трех случаях: когда один объект инициализирует другой, когда ко­пия объекта передается в функцию и когда создается временный объект (обычно он служит возвращаемым значением). Например, любая из следующих инструкций вызывает инициализацию:

myclass x = у; // инициализация

F(x); // передача параметра

У = F1(); // получение временного объекта

Ниже приведен пример, где необходим явный конструктор копирования. Эта программа со­здает очень простой «безопасный» тип массива целых чисел, предотвращающий вывод за грани­цы массива. Память для каждого массива выделяется с использованием оператора new и в каждом объекте поддерживается работа с указателем на выделенную память.

#include <iostream.h>

#include <stdlib.h>

class array

{

int *p;

int size;

public:

array(int s) { p = new int[s]; if(!p) exit(1); size = s; }

~array() { delete [] p; }

array(const array &a);

void put(int i, int j) { if(i>=0 && i<size) p[i] = j; }

int get(int i) { if(i>=0 && i<size) return p[i]; else return 0; }

};

array::array(const array &a)

{

p = new int[a.size]; if(!p) exit(1);

for(int i=0; i<a.size; i++) p[i] = a.p[i];

}

int main()

{

array num(10);

int i;

for(i=0; i<10; i++) num.put(i, i);

for(i=9; i>=0; i--) cout << num.get(i);

cout << "\n";

// создание другого массива и инициализация его значениями num

array x(num); // вызов конструктора копирования

for(i=0; i<10; i++) cout << x.get(i);

return 0;

}

Когда объект num используется для инициализации х, то вызывается конструктор копирова­ния, выделяющий новую память, адрес которой помещается в х.р, а затем содержание массива num копируется в массив объекта х. Таким образом, объекты х и num содержат массивы с одина­ковыми значениями, но каждый массив независим от другого и располагается в своей области памяти. Если бы конструктор копирования не был создан, то использовалась бы инициализация по умолчанию путем побитового копирования, так что массивы х и num разделяли бы между собой одну и ту же область памяти.

Конструктор копирования вызывается только для инициализации. Например, следующие инст­рукции не содержат вызова конструктора копирования:

array a(10);

array b(10);

b = а; // не вызывает конструктор копирования

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



<== предыдущая лекция | следующая лекция ==>
Передача объектов в функции | Инициализация массивов объектов


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.005 сек.