Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по прогр.ч.2.doc
Скачиваний:
3
Добавлен:
01.05.2025
Размер:
293.89 Кб
Скачать

Лекция 6

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

В языке С++ функции могут возвращать в качестве результатов объекты. Чтобы функция могла вернуть объект как результат, нужно объявить в качестве ее типа имя класса и обеспечить возврат объекта этого типа через оператор return.

Рассмотрим пример.

#include <iostream.h>

class MyClass

{int value;

public:

MyClass(int i)

{value=i;

cout<<”В конструкторе.\n”;}

~MyClass()

{cout<<”Разрушение объекта.\n”;}

int getvalue()

{return value;}

MyClass change()

{ MyClass object(value*2);

return object;}

/* функция change() возвращает объект, у которого поле value в 2 раза больше поля вызывающего объекта. */

};

//Внешняя функция

void display(MyClass object)

{cout<<object.getvalue()<<’\n’;}

void main()

{MyClass a(10);//создание объекта а и инициализация поля value значением

10

display(a);

a=a.change();/*создание нового объекта и присваивание его значения объекту а */

display(a);

cout<<”После выхода из функции display().\n”;}

Результат

В конструкторе.

10

Разрушение объекта.

В конструкторе.

Разрушение объекта.

Разрушение объекта.

20

Разрушение объекта.

После выхода из функции display()/

Разрушение объекта.

В этом примере функция change() создает локальный объект object класса MyClass, в котором его элемент value содержит вдвое большее значение, чем соответствующий элемент вызывающего объекта. Этот объект возвращается функцией change() и присваивается объекту а функции main(). Затем объект object разрушается , о чем свидетельствует первое сообщение “Разрушение объекта”.

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

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

Кроме того, побочные эффекты могут возникать при инициализации одного объекта другим. Например, допустим, что класс MyClass выделяет ДП для каждого объекта., и объект А является его экземпляром. Предположим, что объект А инициализирует объект В:

MyClass B=A;

Объект В будет копией объекта А. Следовательно, объект В также будет ссылаться на область памяти, выделенную объектом А. Если класс содержит деструктор, то при уничтожении А и В одна и та же область памяти будет освобождаться дважды. Возникает ошибка.

В основе перечисленных проблем лежит создание копии объекта. Поэтому нужно создавать собственный конструктор копии.

Формат конструктора копии

< имя класса>{const <имя класса>& object)

{<тело конструктора>}

Здесь object- это ссылка на объект, который используется для инициализации другого объекта.

Рассмотрим пример программы, в которой необходим собственный конструктор копии при инициализации одного объекта другим.

#include <iostream>

class array

{int *p_int;//указатель на целое число

int size;//длина массива

public:

array(int n)

{p_int=new int[n];

size=n;

}

~array()

{delete []p_int;}

array(const array &a);//прототип конструктора копии

void put(int i, int value)

{if(i>=0 && i<size)

p_int[i]=value;}

/* эта функция записывает значение value в элемент массива p_int c индексом i */

int get(int i)

{return p_int[i];}

//возвращает элемент массива p_int по индексу

};

array::array(const array & a)

{int i;

p_int=new int[a.size];

size=a.size;

for(i=0; i<size;i++}

p_int[i]=a.p_int[i];

}

void main()

{array massiv(10);

int i;

for(i=0; i<10;i++)

massiv.put(i);

for(i=0; i<10;i++)

cout<<”\n”<<massiv.get(i);

array x=massiv:

//Вызывается конструктор копии, который в объект x записывает копию объекта massiv, но адреса p_int у них разные */

for(i=0; i<10;i++)

cout<<”\n”<<x.get(i);

}

При вызове конструктора копирования для нового массива выделяется память. Адрес этой памяти хранится в поле x.p_int. Таким образом, объекты x и massiv содержат одинаковые массивы. Однако эти массивы имеют разные адреса: massiv.p_int не равен x.p_int. Деструктор будет уничтожать копию объекта, в котором массив записан по адресу x.p_int , а исходный объект- по адресу massiv.p_int.

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