Class string
{
char *Str;
int size;
public:
string &operator= (string&);
};
string& string::operator= (string& right)
{
if (Str !=NULL) delete Str; // Освободить динамическую память
size = right.size; // Резервировать память
Str = new char[size + 1];
strcpy(Str,right.Str); // Копировать строки
return *this; }
Перегруженные операции индексирования, вызова функций, инкремента и декремента префиксных и постфиксных.Переопределение операции () позволяет использовать синтаксис вызова функции применительно к объекту класса (имя объекта с круглыми скобками). Количество операндов в скобках может быть любым. Переопределение операции [] позволяет использовать синтаксис элемента массива (имя объекта с квадратными скобками).
//------Переопределение операций [] и ()
#include <string.h>
class string // Строка переменной длины
{
char *Str; // Динамический массив символов
int size; // Длина строки
public:
// Операция выделения подстроки
string operator()(int,int);
// Операция выделения символа
char operator[](int);
int operator[](char*); // Операция поиска подстроки
};
//------ Операция выделения подстроки -------------------
string string::operator()(int n1, int n2)
{
string tmp = *this;
delete tmp.Str;
tmp.Str = new char[n2-n1+1];
strncpy(tmp.Str, Str+n1, n2-n1);
return tmp; };
Пример переопределения операции инкремента приведен выше. Переопределение декремента производится аналогично. Заметим только, что когда операции ++ и -- перегружены, префиксное использование и постфиксное в классическом С++ различить невозможно. В современной версии языка (Microsoft Visual C++ 6.0) принято соглашение, что перегрузка префиксных операций ++ и -- ничем не отличаются от перегрузки других унарных операций, то есть дружественные функции operator++() и operator--() с одним параметром некоторого класса определяют префиксные операции ++ и --. Операции - члены класса без параметров определяют те же префиксные операции. При расширении действия постфиксных операций ++ и –– операции-функции должны иметь еще один дополнительный параметр типа int. Если для перегрузки используется операция - член класса, то она должна иметь один параметр типа int. Если операция определена как дружественная функция, то ее первый параметр должен иметь тип класса, а второй - тип int. Когда в программе используется соответствующее постфиксное выражение, то операция - функция вызывается с нулевым целым параметром.
Рассмотрим пример применения разных операций - функций для постфиксной и префиксной операций ++ и --.
class pair // класс «пара чисел»
{
int N; // целое
double x; // вещественное
friend pair& operator++(pair&); //дружественная для префикса
friend pair& operator++(pair&,int);//дружественная для постфикса
public:
pair (int n, double xn) //конструктор
{ N = n; x = xn; };
void display () //вывод значения
{ printf (”N = % d x = % f ”, N, x); };
pair& operator–– () //член для префикса
{ N /= 10; x /= 10; return *this; };
pair& operator–– ( int k) //член для постфикса
{ N /= 2; x /= 2; return *this; };
};
pair& operator++ ( pair & P) // дружественная для префикса
{ P.N *= 10; P.x *= 10; return P; };
pair& operator++ (pair & P, int k) // дружественная для постфикса
{ P.N = P.N * 2 + k; P.x = P.x * 2 + k; return P; };
void main()
{
pair Z (10, 20.0); //вызов конструктора
Z.display(); //N = 10 x = 20
++Z; Z.display(); //N = 100 x = 200
--Z; Z.display(); //N = 10 x = 20
Z++; Z.display(); //N = 20 x = 40
Z--; Z.display(); //N = 10 x = 20
};
Для демонстрации полной независимости смысла перегруженной операции от ее традиционного значения в операциях - функциях для префиксных операций ++ соответствует увеличению в 10 раз, а –– уменьшению в 10 раз. Для постфиксных операций ++ определена как увеличение в 2 раза, а - -- уменьшение в 2 раза. Попытки использовать в постфиксных операциях значение дополнительного параметра int k подтверждают его равенство 0.
Перегрузка new, delete.Операции создания и уничтожения объектов в динамической памяти могут быть переопределены следующим образом
void* operator new(size_t size);
void operator delete (void *);
где void* - указатель на область памяти, выделяемую под объект, size - размер объекта в байтах, size_t - тип размерности области памяти, int или long.
Переопределение этих операций позволяет написать собственное распределение памяти для объектов класса.
Операции, не допускающие перегрузки. В С++ существует несколько операций, не допускающих перегрузки:
. прямой выбор члена объекта класса;
.*обращение к члену через указатель на него;
?:условная операция;
::операция указания области видимости;
sizeofоперация вычисления размера в байтах;
#препроцессорная операция.
Преобразование типов, определяемых пользователем с помощью конструкторов и операций преобразования.При работе со стандартными типами данных в Си имеют место явные и неявные преобразования их типов. По аналогии для классов также могут быть определены такие операции - они ассоциируются с конструированием объектов класса. Так, если в программе встречается преобразование типа (класса) "yyy" к типу (классу) "xxx", то для его осуществления в классе "xxx" необходим конструктор вида xxx(yyy &);
Сами преобразования типов происходят в тех же самых случаях, что и обычные преобразования базовых типов данных:
· при использовании операции явного преобразования типов;
· при выполнении операции присваивания, если она не переопределена в виде "xxx=yyy" (транслятором создается временный объект класса "xxx", для которого вызывается указанный конструктор и который затем используется в правой части операции присваивания);
· при неявном преобразовании типа формального параметра функции при передаче его по значению (вместо конструктора копирования);
· при неявном преобразовании типа результата функции при передаче его по значению (вместо конструктора копирования);
· при определении объекта класса "xxx" одновременно с его инициализацией объектом класса "yyy" (вместо конструктора копирования)
yyy b;
xxx a = b;
При конструировании объекта класса "xxx" с использованием объекта класса "yyy" естественно должна быть обеспечена доступность необходимых данных последнего (например, через дружественность).
В качестве примера рассмотрим обратное преобразование базового типа long к типу dat - количество дней от начала летоисчисления преобразуется к дате. Здесь же рассмотрим другой класс - man, в котором одним из элементов личной части является дата. Значение этого объекта копируется при преобразовании типа man в тип dat.
static int days[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
class man;