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;