
Лекции по ППВиС (17 шт, ppt) Романов ВИ 2011 1ый семестр / Л5_Перегрузка операторов
.ppt
21
Определение манипуляторов с параметрами 2
Продолжение примера:
char *money::CurM; // Static pointer
void func( ios_base& os, char * somename )
{
money::setpic(somename);
}
_Smanip<charp> setpic(char * somename)
{
return (_Smanip<charp>(&func, somename));
}
void main ()
{
money amt = (long)54321;
cout << setpic( "$") << "amount = " << amt << endl; // Альтернатива Br или €
}

22
Перегрузка оператора new
ВС++ имеются две возможности перегрузки операторов new() и delete()
-локально (в пределах класса) и глобально (в пределах программы). Эти операторы имеют правила переопределения, отличные от рассмотренных правил переопределения других операторов.
Одна из причин перегрузки этих операторов состоит в том, чтобы придать им допол-нительную семантику, например, для обеспечения выдачи диагностической информа-ции, или увеличения защищенности от ошибок. Кроме того, класс может иметь более эффективную схему распределения памяти, чем та, которая обеспечивается системой.
Оператор new можно задать в следующих формах:
<::> new <аргументы> имя_типа <инициализирующее_выражение>;
<::> new <аргументы> имя_типа [ ];
Параметр ”аргументы” можно использовать либо для того, чтобы различить разные версии глобальных операторов new, либо для использования их в теле функции operator. Доопределенную функцию operator new можно объявить:
void *operator new(size_t t, <список _аргументов>); void *operator new[](size_t t, <список _аргументов>);
Вторая форма используется для выделения памяти для массивов. Возвращаемое значение всегда должно иметь тип void *. Единственный
обязательный аргумент функции operator всегда должен иметь тип size_t.

23
Перегрузка оператора new - пример
#include "iostream“ using namespace std;
void *operator new(size_t tip, int kol) |
//глобальная ф-ция operator |
new |
// с одним параметром |
{ cout << "GF 1" <<endl; |
|
return new char[tip*kol]; |
|
}
void *operator new(size_t tip,int n1,int n2) //глобальная ф-ция operator new
{ cout << "GF 2" <<endl; // с двумя параметрами void *p=new char[tip*n1*n2];
return p;
}
class cls
{ char a[40]; public:
cls(char *aa){ strcpy(a,aa); } ~cls(){}
void *operator new(size_t,int);
};

24
Перегрузка оператора new - пример
void *cls::operator new(size_t tp,int n) // локальная функция operator new
{ cout << "LF " <<endl; return new char[tp*n];
}
void main()
{cls obj("Overload of the operator new"); float *ptr1;
ptr1=new (5) float; |
// вызов 1 глобальной функции |
operator |
new |
|
|
ptr1=new (2,3) float; |
// вызов 2 глобальной функции |
operator |
new |
|
|
ptr1=new float; |
// вызов сиcтемной глобальной функции |
cls *ptr2=new (3) cls("aa"); // вызов локальной функции operator
warning C4291: 'void *cls::operator new(size_t,int)' : no matching operator delete found; memory will not be freed if initialization throws an exception

25
Перегрузка оператора delete
Оператор delete разрешается доопределять только по
отношению к классу. В то же время можно заменить
системную версию реализации оператора delete на свою.
Доопределенную функцию operator delete можно
объявить:
void operator delete(void *p<,size_t t>); void operator delete[](void *p<,size_t t>);
Функция operator должна возвращать значение void и
имеет один обязательный аргумент типа void * - указатель на область памяти, которая должна быть освобождена.

26
Перегрузка оператора delete - пример
…
class cls {
…
void operator delete(void *);
…
}
void cls::operator delete(void *p) |
// локальная функция operator |
|
{ cout << “LF DELETE" <<endl; |
|
|
delete p; |
// вызов системной функции delete |
|
} |
|
|
void operator delete[](void *p) |
// глобальная функция operator |
|
{ cout << “GF DELETE" <<endl; |
|
|
delete p; |
// вызов системной функции delete |
|
} |
|
|

27
Перегрузка оператора delete - использование
void main() |
|
|
{ cls obj("перегрузка операторов NEW и DELETE"); |
|
|
float *ptr1; |
// вызов глобальной ф-ции |
доопр. оператора |
ptr1=new (5) float; |
||
new |
// вызов глобальной ф-ции |
доопр.оператора |
delete [] ptr1; |
||
delete |
|
|
cls *ptr2=new (10) cls("aa"); // вызов локальной функции доопределения
// оператора new (из класса cls) delete ptr2; // вызов локальной функции
доопределения
// оператора delete (из класса cls)
}использоваться оператор delete[], так как это приведет к бесконечной рекурсии. При выполнении инструкции системный оператор delete ptr2 сначала вызывается локальная функция доопределения оператора delete для класса cls, а затем из нее глобальная функция переопределения delete.

28
Перегрузка операторов new – delete
warning C4291: 'void *cls::operator new(size_t,int)' : no matching operator delete found; memory will not be freed if initialization throws an exception
Нужны добавки!
class cls { …
void operator delete(void *,int);
…
};
void cls::operator delete(void *p, int n) // локальная функция
operator |
|
{ |
|
cout << "LFD" <<endl; |
|
delete p; |
// вызов системной функции |
delete |
|
} |
|