52
class Function {
public:
int
operator()(char*);
};
int Function::operator()(char* s)
{
cout << “\”” << s << “\””;
}
Function fn;
int x = fn(“Hello”);
// Выводит в cout строку “Hello”
Оператор
()
может возвращать любой тип и принимать любые аргументы. При этом он подчиняется
тем же правилам, что и любая другая функция. Оператор
()
перегружается только в форме функции
класса.
Оператор new
Изобретая
новый язык, приходится изобретать собственные правила. Одно из новых правил C++
гласит, что имя оператора не обязано состоять из одних служебных символов. Исключение составляют
операторы
new
и
delete
. Оператор new вызывается всякий раз, когда компилятор считает, что настало
время выделить из кучи память для нового объекта. Используемый здесь термин
объект относится к
любым динамическим данным, включая
int
,
char*
и т.д., а не только к экземплярам ваших классов.
Оператор
new
по умолчанию имеет следующий интерфейс:
void* operator new(size_t bytes);
Единственный аргумент — количество выделяемых байт, возвращаемое значение — адрес выделенной
области. Оператор
new
никогда не должен возвращать
NULL
; вместо этого при нехватке памяти
инициируется исключение (см. главу 4). Реализация оператора
new
по умолчанию изменяется от
простого вызова функции
mallос
или
callос
до нестандартных средств управления памятью,
прилагаемых к компилятору.
Оператор
new
может перегружаться как в форме внешней функции, так и в форме функции класса. При
перегрузке в форме функции класса он наследуется, поэтому выделение памяти в производных классах
будет осуществляться так же, как и в базовом классе, перегрузившем оператор
new
.
class Foo {
public:
void* operator new(size_t bytes);
};
void* Foo::operator new(size_t bytes)
{
if (bytes < MAXBYTES)
//
Нестандартное выделение памяти для блоков малого размера
else return ::operator new(bytes);
}
Разумеется, всеобщая перегрузка
глобального оператора
new
затруднит создание переносимого кода,
поэтому обычно предпочтительным вариантом является перегрузка в форме функции класса. Она
имеет дополнительные преимущества: из перегруженной функции можно вызвать оператор
new
по
умолчанию, как это делается в предыдущем фрагменте. Оператор
new
также может перегружаться для
других сигнатур. Хотя дополнительные сигнатуры не будут вызываться компилятором автоматически,
они оказывают большую помощь при реализации нестандартного управления памятью, в
которой
можно вызвать конкретную версию оператора
new
.
class Pool { // Нестандартный пул памяти
public:
virtual void* Allocate(size_t bytes);