    В двух операторах вывода в поток используется перегруженный оператор -> 
для доступа к функциям-членам GetX() и GetY() объекта t класса TAnyClass. На 
самом деле, эти операторы выполняются так, как приведенные ниже: 

    cout « (t.operator->())->GetX() « '\n'; cout « (t.operator->())->GetY() « '\n'; 

    Поэтому программа отобразит метки перед значениями, возвращаемыми 
функциями GetX() и GetY(): 

    Accessing member: 100 
    Accessing member: 200 

    Операторы инкремента и декремента 

    В ранних версиях C++ было невозможно определить отдельные перегруженные 
операции для постфиксных и префиксных операторов ++ и --. Теперь это возможно, 
как показано в классе TAnyClass: 

    class TAnyClass { 
       int x; 
    public: 
       TAnyClass(int xx) { x = xx;   } 
       int operator++() { return ++x;  }	// Префиксный ++object 
       int operator++(int) { return x++;  )   	// Постфиксный object++ 
       int operator--() {  return --x;   }                // Префиксный --object 
       int operator--(int) { return х--;  }	// Постфиксный object--
       int GetX(void) {  return x;  } 
    }; 

    Функция-член operator++() определяет префиксный оператор инкремента для 
объекта типа TAnyClass; эта функция не имеет параметров. Функция-член 
operator++(int) определяет постфиксный оператор инкремента для объекта типа 
TAnyClass; C++ присваивает нуль единственному целочисленному параметру. 
    Демонстрационные функции реализуются встраиваемыми, однако они могут 
реализоваться и отдельно. Для объекта v типа TAnyClass выражение ++v вызовет 
перегруженный префиксный оператор ++. В действительности выполняется оператор 
x.operator++();. Выражение v++ вызовет перегруженный постфиксный оператор ++ и 
выполнится, как x.operator++(0);. Операторы декремента работают аналогичным образом. 
    Поэкспериментируйте с объявленным выше классом, добавив к нему программу 
на C++, где функция main() реализована следующим образом:	

    main()
   { 
      TAnyClass t(100); 
      cout « "t == " « t.GetX() « "; ++t == " « ++t « '\n'; 
      cout « "t == " « t.GetX() « "; t++ == " « t++ « '\n'; 
      cout « "t == " « t.GetxO « ";   --t == " « --t « '\n'; 
      cout « "t == " « t.GetxO « ";   t-- == " « t-- « '\n';
  } 


    Другие вопросы, касающиеся перегрузки операторов 

    Получив некоторое представление о перегрузке операторов, необходимо иметь 
в виду следующие факты. 
    •  C++ "не понимает" семантики перегруженного оператора. Вы должны 
обеспечить осмысленные функции перегрузки операторов. 
    •   C++ не может выводить сложные операторы из простых. В классе, в 
котором объявлены функции перегрузки операторов operator*() и operator=(), C++ 
не сможет вычислить выражение а *= b до тех пор, пока вы не перегрузите 
operator *=().
   •  Никогда не изменяйте синтаксис перегруженных операторов. Бинарные операторы 
должны оставаться бинарными, унарные — унарными. Например, нельзя создать 
унарное деление, поскольку такой встроенной возможности в C++ не существует. 
   •  Нельзя изобретать новые операторы. Вы можете перегружать только операторы, 
перечисленные в табл. 15.1. Нельзя перегружать символы препроцессора # и ##. 

    Перегрузка и управление памятью 

    В программах, написанных на ANSI С, используются функции malloc() и free() 
вместе с им подобными библиотечными функциями для выделения и освобождения 
блоков памяти в куче. В отличие от этого, в программах, написанных на C++,
используются операторы new и delete. На самом деле, в большинстве 
реализаций С++ new и delete скрыто реализуются вызовами функций malloc() и 
free(). Поэтому некоторые программисты на C++ не видят для себя особой разницы 
между способами управления памятью в ANSI Сив C++. 


    Глава 15. Передовые средства C++     379 
