Теоретические сведения для студентов специальностей «Экономика и организация производства», страница 17

Имеется интересная возможность определить, вызван ли конструктор оператором new или каким-либо другим способом. Если конструктор вызван через оператор new, то указатель this на входе в конструктор имеет значение 0. В другом случае он указывает на пространство, занятое объектом. Отсюда следует, что можно написать конструктор, который будет отводить память, например, только тогда, когда он был вызван оператором new. К сожалению, для деструктора такой возможности нет.

Тема 5. ПЕРЕГРУЗКА ОПЕРАТОРОВ

Практически в любом процедурном языке используются изначально перегруженные операторы (операции). Так, арифметические операции "знают", как манипулировать с различными типами данных (например, в языках Си, Паскаль операция "+" знает, как обрабатывать типы int, float и др.). Очевидно, что хотя используется одна и та же арифметическая операция, генерируемый исполняющий код операций разный, так как целые и вещественные числа представляются в памяти по-разному. Мы уже использовали перегруженный знак операции сдвига ">>" и "<<" для выполнения ввода-вывода в С++. Кроме того, С++ дает возможность перегружать практически все предопределенные (имеющиеся в конкретном языке) операции. Рассмотрим, как реализуется представленная пользователю возможность переопределения операций.

Для переопределения операции следует описать функцию, которая в качестве своего имени использует ключевое слово operator и символ перегружаемой операции. Если некоторый оператор перегружен для какого-либо класса, то он позволяет реализовать новые действия в контексте этого класса.

Представим задачу, в которой необходимо часто вычислять среднее значение параметров двух объектов. Можно выполнять эту операцию при помощи вызова специально разработанной функции, но гораздо удобнее переопределить некоторую операцию (оператор-функцию) и использовать ее в дальнейшем для нахождения средних значений. Для этого необходимо выбрать одну из уже существующих операций в языке С++. Пусть этой операцией будет, например, операция "^" - (поразрядное исключающее или). Переопределим ее таким образом, чтобы данная операция вычисляла средние значения атрибутов (некоторых показателей a и b, присущих совокупности объектов - классу объектов) двух суммируемых объектов.

Пример:

#include <iostream.h>    //файл описаний иерархии потоков ввода-вывода

class my_obj { int a,b;    //атрибутыобъектов public:

my_obj *ptr;          //указатель на объект класса

my_obj(int x=0,int y=0)

//конструктор принимает два параметра с заданными по умолчанию

//значениями

          {a=x; b=y;}            //инициализация переменных

my_obj & operator^ (my_obj obj_two) //заголовокфункции

//переопределения операции ^. Имя функции "operator^", функция

//принимает объект obj_two в качестве аргумента и возвращает ссылку

//на объект класса my_obj.

{my_obj sum;                           //sum - объект для получения результата

sum.a=(a+obj_two.a)/2;            //вычисление усредненных значений

sum.b=(b+obj_two.b)/2; return *(ptr=&sum); }

//возврат результирующего объекта

my_obj operator= (my_obj obj_sec)   //переопределение оператора =

{a=obj_sec.a;                            //для присваивания объектов класса

b=obj_sec.b; return (*this);}     //возвращается ссылка на объект,

//для которого вызывается функция переопределения "="

friend ostream& operator<< (ostream & a,my_obj obj_rez); };          //переопределениеоператора

//вывода для вывода объектов класса реализуется

//дружественнойфункцией

ostream& operator<< (ostream & a,my_obj obj_rez)

//определение функции

{ cout<<"\nзначение атрибутов объекта:\na="<<obj_rez.a<< ";

b="<<obj_rez.b; return a; }

void main() { my_obj a1(10,20), a2(45,30),sum1;

//объявление объектов

          sum1=a1^a2;                  //вычисление среднего значения