// Генерирование исключения при неудаче.

 р = malloc(size);

 if(!р) {

  bad_alloc ba;

  throw ba;

 }

 return p;

}

// Перегрузка оператора delete для класса three_d.

void three_d::operator delete(void *p)

{

 cout << "Удаление объекта класса three_d.\n";

 free(p);

}

// Перегрузка оператора delete для массива объектов типа three_d.

void three_d::operator delete[](void *p)

{

 cout << "Удаление массива объектов типа three_d.\n";

 free(р);

}

// Отображение координат X, Y, Z.

void three_d::show()

{

 cout << x << ", ";

 cout << у << ", ";

 cout << z << "\n";

}

int main()

{

 three_d *p1, *p2;

 try {

  p1 = new three_d[3]; // выделение памяти для массива

  р2 = new three_d(5, 6, 7); // выделение памяти для объекта

 }

 catch (bad_alloc ba) {

  cout << "Ошибка при выделении памяти.\n";

  return 1;

 }

 p1[1].show();

 p2->show();

 delete [] p1; // удаление массива

 delete р2; // удаление объекта

 return 0;

}

При выполнении эта программа генерирует такие результаты.

Выделение памяти для массива three_d-oбъeктoв.

Создание объекта 0, 0, 0

Создание объекта 0, 0, 0

Создание объекта 0, 0, 0

Выделение памяти для объекта класса three_d.

Создание объекта 5, 6, 7

0, 0, 0

5, б, 7

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

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

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

Удаление массива объектов типа three_d.

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

Удаление объекта класса three_d.

Первые три сообщения Создание объекта 0, 0, 0 выданы конструктором класса three_d (который не имеет параметров) при выделении памяти для трехэлементного массива. Как упоминалось выше, при выделении памяти для массива автоматически вызывается конструктор каждого элемента. Сообщение Создание объекта 5, б, 7 выдано конструктором класса three_d (который принимает три аргумента) при выделении памяти для одного объекта. Первые три сообщения Разрушение объекта выданы деструктором в результате удаления трехэлементного массива, поскольку при этом автоматически вызывался деструктор каждого элемента массива. Последнее сообщение Разрушение объекта выдано при удалении одного объекта класса three_d. Важно понимать, что, если операторы new и delete перегружены для конкретного класса, то в результате их использования для данных других типов будут задействованы оригинальные версии операторов new и delete. Это означает, что при добавлении в функцию main() следующей строки будет выполнена стандартная версия оператора new.

int *f = new int; // Используется стандартная версия оператора new.

И еще. Операторы new и delete можно перегружать глобально. Для этого достаточно объявить их операторные функции вне классов. В этом случае стандартные версии С++-операторов new и delete игнорируются вообще, и во всех запросах на выделение памяти используются их перегруженные версии. Безусловно, если вы при этом определите версию операторов new и delete для конкретного класса, то эти "классовые" версии будут применяться при выделении памяти (и ее освобождении) для объектов этого класса. Во всех же остальных случаях будут использоваться глобальные операторные функции.

Перегрузка nothrow-версии оператора new

Можно также создать перегруженные nothrow-версии операторов new и delete. Для этого используйте такие схемы.

// Перегрузка nothrow-версии оператора new.

void *operator new(size_t size, const nothrow_t &n)

{

 // Выделение памяти.

 if(success) return pointer_to_memory;

 else return 0;

}

// Перегрузка nothrow-версии оператора new для массива.

void *operator new[](size_t size, const nothrow_t &n)

{

Перейти на страницу:

Все книги серии Изучайте C++ с профессионалами

Похожие книги