Классы и размещение объектов в heap-памяти


Под динамической памятью понимается в данном контексте heap-память. Для управления используются операторы new, delete. Правила их использования просты:

· если какая-либо переменная-указатель экземпляра инициализируется оператором new в конструкторе, то деструктор должен освободить память оператором delete, параметром которого является эта переменная указатель.

· все конструкторы должны базироваться для некоторого указателя либо на операторе new либо на new[], но ни в коем случае для одного и того же указателя нельзя их смешивать. Тогда и освобождение, соответственно, реализуется либо с помощью delete либо delete[].

 

Пример

Строится программная модель очереди.Будем считать, что экземплярами очереди являются структуры следующего вида:

 

struct Node

{

Item item;//данные о элементе

Struct Node* next;//указатель на следующий элемент.
};//Item – заранее определён

 

class Queue

{

enum {q_size = 10};

private:

Node* front;//указатель начала

Node* rear;//указатель конца

int items;//тек. кол-во элементов в очереди

const int qsize;//макс. кол-во элементов в оереди

public:

Queue(int sq = q_size);//конструктор по умолчанию

~Queue();//деструктор

bool isempty() const;//определяет пуста ли очередь

bool isfull() const;//оперделяет полна ли очередь

int queuecount() const;//кол-во элементов

bool enquene(const Item &item);//добавление элемента

bool dequeue(Item &item);//удаление элемента

};

 

Реализация класса

Мы не можем в конструкторе прямо указать qsize = sq, т.к. qsize – константа (const). Для обхода этой ситуации в Си используется специальный синтаксис – список инициализаторов, он включает перечень инициализаторов, разделённых запятыми. Списку, предшествует двоеточие:

 

Queue::Queue(int qs):qsize(sq)//инициализация qsize к qs

{

front = rear = NULL;

items = 0;
}

 

Только конструкторы могут применять список инициализаторов. Можно переписать конструктор и так:

Queue::Queue(int qs):qsize(sq),front(NULL),rear(NULL),items(0){}

 

Статичные элементы не могут инициализироваться списком инициализаторов!

 

Реализация методов:

 

bool Queue::enquene(const Item &item)

{

if (isfull()) return false;//очередь полна

Node* add = new Node;//созд узла

if (add == NULL) return false;//переполнение хипа

add->item = item;//запись данных

add->next = NULL;

items++;

if (front==NULL)//занесение в список очереди

front = add;

else rear->next = add;

read = add;

return true;

}

bool Queue::dequeue(Item &item)

{

if (front == NULL) return false;//очередь пуста

item = front ->item;//выборка из очереди

items--;

Node* temp = front;

front = front->next;

delete temp;//удаление свзующего элемента

if (items ==0) rear = NULL;

return true;

}

 

 

Необходим явный деструктор, чтобы при уничтожении всего объекта очереди удалить предварительно из неё все узлы:

Queue::~Queue()

{

Node* temp;

while (front!=NULL)

{

temp = front;

front = front -> next;

delete temp;

}

}

 

Желательно доопределить для полноты конструктор копирования и перегрузить оператор присваивания. Это делается добавлением следующих определений в раздел private декларации класса:

 

1. Queue(const Queue& q):qsize(q.qsize){…}; В теле «...» - надо пройти в цикле по списку всех элементов в q, разместить их копии в heap- памяти, связать в список и, соответственно, заполнить front, rear и items для нового объекта.

2. Queue& operator=(const Queue &q) {… return *this;} – Здесь практически проделать то же самое, но контролируя возможность того, что qsize < q.qsize

 

Поэлементное копирование, реализуемое обычным оператором «=» не годится, поэтому мы его перекрыли. Не годится и стандартное определение конструктора копирования, поэтому все определения мы упрятали в приватную часть декларации.

 

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

 



Дата добавления: 2016-05-26; просмотров: 1523;


Поиск по сайту:

Воспользовавшись поиском можно найти нужную информацию на сайте.

Поделитесь с друзьями:

Считаете данную информацию полезной, тогда расскажите друзьям в соц. сетях.
Poznayka.org - Познайка.Орг - 2016-2024 год. Материал предоставляется для ознакомительных и учебных целей.
Генерация страницы за: 0.014 сек.