Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Классы, использующие свободную память

Поиск

Причины, по которым приходится создавать классы с динамическим управлением памятью. Пример такого класса: функция, заданная таблично. Состояние класса включает в себя информацию о размере таблицы (количество узлов в задании функции) и массивы для хранения значений аргумента (х) и соответствующих значений функции (y). Массивы определяются через соответствующие указатели, размер таблицы определяет требуемый объем памяти. Кто выделит память? - конструктор. Пример разработки соответствующего класса.

class Function{

private:

float * Ptrx, * yPtr;

int size;

public:

Function(); // пустой конструктор

Function(int sz); // инициализирующий конструктор

~Function();

...

};

Function::Function()

{

size = 0;

xPtr = yPtr = NULL;

}

Function::Function(int sz)

{

size = sz;

xPtr = new float[size];

yPtr = new float[size];

}

Function::~Function()

{

delete [] xPtr;

delete [] yPtr;

}

Возникающие проблемы

Если в прикладной программе в некотором внутреннем блоке создается переменная типа “Указатель на класс” и ей присваивается значение некоторой другой – глобальной переменной: для классов (структур) определена операция присваивания - побайтное копирование:

Function f1[5]; f1 5 f2 5

...

{

Function f2;

f2 = f1;

...

}

 

В момент выхода из блока переменная f2 разрушается – для нее работает деструктор класса. В результате будет разрушена и переменная f1!

Результат не изменится, если во внутреннем блоке вместо присваивания использовать инициализацию (в этом случае будет работать копирующий конструктор по умолчанию – тоже побайтное копирование):

{

Function f2 = f1;

...

}

Решение проблемы

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

Копирующий конструктор (объявление в определении класса):

...

Function(const Function&);

...

Копирующий конструктор должен:

- Выделить новую память для создаваемого экземпляра класса,

- Скопировать в нее состояние существующего экземпляра класса.

Реализация:

Function::Function(const Function &f)

{

size = f.size;

xPtr = new float[size];

yPtr = new float[size];

for(int i = 0; i < size; i++){

xPtr[i] = f.xPtr[i];

yPtr[i] = f.yPtr[i];

}

}

Перегруженный оператор присваивания (объявление в определении класса; функция-член класса):

...

Function& operator =(const Function&);

...

Перегруженный оператор присваивания должен:

- Освободить память, занимаемую экземпляром класса – адресата оператора присваивания (указанного слева от присваивания),

- Выделить новую память для нового значения экземпляра класса – адресата,

- Скопировать в нее значение экземпляра класса, указанного справа от присваивания (параметр оператора присваивания),

- Проверить возможность записи присваивания типа x = x.

Реализация:

Function& Function::operator =(const Function &f)

{

if(this!= &f){ // проверка ситуации x = x

;

delete [] xPtr;

delete [] yPtr;

xPtr = yPtr = NULL;

if(size = f.size){ // проверка ситуации, когда у объекта f нет памяти

xPtr = new float[size];

yPtr = new float[size];

for(int i = 0; i < size; i++){

xPtr[i] = f.xPtr[i];

yPtr[i] = f.yPtr[i];

}

}

}

return *this;

}



Поделиться:


Последнее изменение этой страницы: 2017-02-07; просмотров: 163; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.144.104.175 (0.009 с.)