Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

О перегрузке операций

Читайте также:
  1. Анализ депозитных операций.
  2. Арифметические преобразования при выполнении арифметических операций вида X op Y
  3. Аудит учета кассовых операций.
  4. Влияние хозяйственных операций на статьи и валюту баланса
  5. Документальное оформление операций по движению материально-производственных запасов
  6. Журнал регистрации хозяйственных операций за январь месяц 2014 г.
  7. Журнал хозяйственных операций за отчетный период, руб.

C++ дает возможность использовать стандартные операции для классов, в дополнение к обычным операциям для фундаментальных типов. Например, для целых переменных справедливо:

int a, b, c;
a = b + c;

Тем не менее, это не очевидно для следующего случая (фактически, это – неверно!):

struct { char product [50]; float price; } a, b, c;
a = b + c;

Присваивание объектов одного и того же класса (или struct) друг другу разрешено (копирующий конструктор по умолчанию!). Ошибка здесь в применении операции сложения, которая не поддерживается для не базовых типов.

Но в C++ операции можно перегрузить(т.е. расширить область их действия в “пространстве” типов) и тогда эти операции можно применять к объектам, создаваемым на основе классов. Вот список всех операций, которые могут быть перегружены:

+ - * / = < > += -= *= /= << >><<= >>= ==!= <= >= ++ -- % & ^! |~ &= ^= |= && || %= [] () new delete

Для перегрузки операции нам нужно написать функцию-член класса, чье имя составлено из ключевого слова operator и, следующего за ним знака (имени) операции, в соответствии с таким синтаксисом (для прототипа):

type operator sign ( parameters );

Вот пример для операции + . Мы собираемся сложить двумерные векторы a (3,1) и b (1,2) . Здесь мы используем покоординатное сложение, так что результат будет (3+1,1+2) = (4,3) .

// vectors: overloading operators example #include <iostream.h> class CVector { public: int x,y; CVector () {}; CVector (int,int); CVector operator + (CVector);};CVector::CVector (int a, int b) { x = a; y = b;}CVector CVector::operator+ (CVector param) { CVector temp; temp.x = x + param.x; temp.y = y + param.y; return (temp);}int main () { CVector a (3,1); CVector b (1,2); CVector c; c = a + b; cout << c.x << "," << c.y; return 0;}

Здесь имя класса присутствует несколько раз в разных контекстах:

CVector (int, int); // имя функции Cvector(конструктор) CVector operator+ (CVector); // функция operator+, которая //возвращает тип CVector

Функция operator + класса CVector – это та функция, которая ответственна за перегрузку арифметической операции + . Она может быть вызвана любым из двух способов:

c = a + b;
c = a.operator+ (b);

àЗаметим, что мы включили в класс пустой конструктор (без параметров) и с пустым телом:

CVector () { };

Это необходимо, поскольку уже существует другой конструктор,

CVector (int, int);

Поэтому никакой конструктор по умолчанию не предполагается, и мы должны явно “его” определить, иначе объявление

CVector c;

включенное в main () не сработает.

Отметим, также, что no-op блок конструктора не рекомендуется использовать, поскольку тогда нет инициализации полей класса. В нашем случае, более подходящим было бы написать что-нибудь подобное:

CVector () { x=0; y=0; };

Но, для простоты, мы это опустили.ß

Если класс включает по умолчанию специальные конструкторы, то в него по умолчанию входит и определение оператора присваивания ( = ) для объектов одного и того же класса. При этом копируется все содержимое нестатических данных объекта-аргумента (справа) в объект слева. Можно, конечно, переопределить функциональность этого оператора, если мы хотим копировать только часть полей класса.

При перегрузке операций рекомендуется не менять математический смысл операций.

Хотя прототип функции operator + выглядит достаточно очевидно, не для всех операций это так. Ниже мы приводим сводную таблицу, показывающую, как должны объявляться различные operator-функции (заменяем @ на знак операции в конкретном случае):

Выражение Операция (@) Член-функция Глобальная функция
@a + - * &! ~ ++ -- A::operator@() operator@(A)
a@ ++ -- A::operator@(int) operator@(A, int)
a@b + - * / % ^ & | < > ==!= <= >= << >> && ||, A::operator@(B) operator@(A, B)
a@b = += -= *= /= %= ^= &= |= <<= >>= [ ] A::operator@(B) -
a(b, c...) () A::operator()(B, C...) -
a->b -> A::operator->() -

* здесь a – объект класса A , b – объект класса B и c – объект класса C .

В этой таблице мы можем видеть, что для некоторых операций имеются два способа перегрузки операций над классами: как метод класса и как глобальной функции. Их использование почти неразличимо, однако не будет лишним напомнить, что не-члены класса не могут иметь доступ к закрытым и защищенным полям класса, если глобальная функция не будет сделана дружественной (friend) нашему классу.

Ключевое слово this

Ключевое слово this представляет внутри класса адрес объекта класса в памяти, во время его существования. Это указатель, чье значение всегда – адрес конкретного, существующего, объекта.

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

// this #include <iostream.h> class CDummy { public: int isitme (CDummy& param);}; int CDummy::isitme (CDummy& param){ if (&param == this) return 1; else return 0;} int main () { CDummy a; CDummy* b = &a; if (b->isitme(a)) cout << "yes, &a is b"; return 0;}

yes, &a is b

Указатель this часто используется в функциях-членах operator = , которые возвращают объекты по ссылке (при этом мы избегаем использования временного объекта). Для приведенного выше примера с вектором, мы могли бы написать функцию operator = таким образом:

CVector& CVector::operator= (const CVector& param){ x=param.x; y=param.y; return *this;}

В действительности, это вероятный код, который сгенерируется для нашего класса, если мы не вставим в класс никакой функции operator = .

 

Когда некоторый метод класса вызывается для конкретного объекта класса, то указатель на этот объект передается методу. Этот указатель, называемый this, указывает на этот конкретный объект. Указатель this есть константный указатель и не может быть изменен (переадресован). Если функция-член является константной функцией, то для нее указатель this есть константный указатель на константу. Если мы хотим модифицировать наш объект внутри функции и вернуть модифицированный объект вызывающей “программе”, мы можем вернуть *this. Вот пример, более сложный, показывающий явное использование указателя this:

 

// В этом примере определяется класс Item, и функции для модификации объекта этого класса. Используя указатель this может быть выполнена модификация объекта с помощью сцепления функций.

#include <iostream.h>

class Item

{

double price;

int quantity;

public:

Item(double p, int q): price(p), quantity(q) { }

Item& modify_price(double new_price)

{

price = new_price;

return *this;

}

Item& modify_quantity(int new_quantity)

{

quantity = new_quantity;

return *this;

}

void print_item() const

{

cout << "price = " << price << endl

<< "quantity = " << quantity << endl;

}

};

int main()

{

Item a(0.29, 100);

a.print_item();

a.modify_price(0.39).modify_quantity(20);

a.print_item();

return 0;

}

Программа выводит:

 

price = 0.29

quantity = 100

price = 0.39

quantity = 20

Заметим, что функции modify_price() или modify_quantity() свою основную работу сделают и в том случае, если они не будут возвращать *this. Но тогда нельзя будет использовать сцепление функций. К тому же, эти функции должны возвращать ссылки. В противном случае, последующая функция вызывается из копии объекта *this, который не является исходным объектом. Например, если бы возврат из функции modify_price был по значению, тогда бы вывод был

 

price = 0.29

quantity = 100

price = 0.39

quantity = 100


Дата добавления: 2015-11-16; просмотров: 46 | Нарушение авторских прав


<== предыдущая страница | следующая страница ==>
Указатели на классы| Статические члены

mybiblioteka.su - 2015-2024 год. (0.011 сек.)