Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

pragma once Hard / Занятие 3

.doc
Скачиваний:
16
Добавлен:
13.03.2015
Размер:
41.98 Кб
Скачать

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

Пример 3.1

Создадим класс MyCls следующего вида:

class MyCls {

int *v;

public:

MyCls(void) {v = new int; *v=0;} //конструктор по умолчанию

MyCls(int x) {v = new int; *v=x;} //конструктор с параметром

MyCls(const MyCls &ob) {v = new int; *v=*(ob.v);} //конструктор копирования

~MyCls(void){delete v;} //деструктор

int get() {return *v;} //метод возвращающий значение

MyCls add(MyCls &); //сложение с указанным классом

};

MyCls MyCls::add(MyCls &a) {

*v = *v + a.get();

return *this;

}

Обратите внимание на указатель this в реализации метода add. Методы в памяти существуют в единственном экземпляре в отличие от полей, которые у каждого объекта свои. Чтобы можно было определить, для какого объекта вызван метод, у метода существует скрытый параметр this, в котором хранится указатель на вызвавший функцию объект. Указатель можно использовать для доступа к элементам объекта, а также для возвращения из метода указателя (return this;) или ссылки (return *this;) на вызвавший объект.

Использование класса демонстрирует следующая программа:

int main() {

MyCls A, B(20), C=B;

cout <<A.get()<<','<<B.get()<<','<< C.get() << endl;

cout <<C.add(B).get()<<endl;

}

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

Можно перегружать любые операции, существующие в С++, кроме

.* ?: :: # ## sizeof

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

  • нельзя создавать новые операции;

  • сохраняются количество аргументов, приоритеты операций, используемые в стандартных типах данных;

  • функции-операции не могут иметь параметров по умолчанию;

  • для стандартных типов данных операции переопределять нельзя.

Функция-операция имеет вид:

тип operator операция (список параметров) { тело функции}

Внутри класса унарная функция-операция является нестатическим методом без параметров, при этом операндом является вызвавший ее объект. Бинарная функция-операция – нестатический метод с параметрами, при этом вызвавший ее объект считается первым операндом.

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

Пример 3.2

class MyCls {

int *v;

public:

MyCls(void) {v = new int; *v=0;} //конструктор по умолчанию

MyCls(int x) {v = new int; *v=x;} //конструктор с параметром

MyCls(const MyCls &ob) {v = new int; *v=*(ob.v);} //конструктор копирования

~MyCls(void){delete v;} //деструктор

int get() {return *v;} //метод возвращающий значение

MyCls add(MyCls &); //сложение с указанным классом

MyCls max(MyCls &);

//перегрузка операторов

MyCls operator +( MyCls &); //ob1+ob2

MyCls operator +(int); //ob+целое число

friend MyCls operator +(int, MyCls &);//целое число+ob

bool operator ==( MyCls &); //ob1==ob2

bool operator ==(int); //ob==целое число

friend bool operator ==(int , MyCls &);//целое число==ob

MyCls operator = ( MyCls &); //присваивание

MyCls operator - ();

};

MyCls MyCls::add(MyCls &a){

*v = *v + a.get();

return *this;

}

MyCls MyCls::max(MyCls &a){

if (*v > a.get()) return *this;

return a;

}

MyCls MyCls::operator +( MyCls &ob){ //ob1+ob2

MyCls new_ob;

*(new_ob.v) = *(this->v) + ob.get();

return new_ob;

}

MyCls MyCls::operator +(int x){ //ob+целое число

MyCls new_ob;

*(new_ob.v) = *v + x;

return new_ob;

}

MyCls operator +(int x, MyCls &ob){ //целое число + ob

MyCls new_ob;

*(new_ob.v) = x + ob.get();

return new_ob;

}

bool MyCls::operator ==( MyCls &ob){ //ob1==ob2

return (*v == ob.get());

}

bool MyCls::operator ==(int x){ //ob==целое число

return (*v == x);

}

bool operator ==(int x, MyCls &ob){ //целое число == ob

return (x == ob.get());

}

MyCls MyCls::operator = ( MyCls &ob){ //присваивание

if (&ob==this) return *this;

if (v) delete v;

v = new int;

*v = ob.get();

return *this;

}

MyCls MyCls::operator - (){ //одноместный минус

*v = -*v;

return *this;

}

int main() {

MyCls A(10), B(20), D;

D = A + B;

cout << D.get() << endl; //30

D = D + 30;

cout << D.get() << endl; //60

B = 40 + D;

cout << B.get() << endl; //100

cout << (A == B) << endl; //0

cout << (A == 10) << endl; //1

cout << (100 == B) << endl; //1

A=-B+A;

cout << A.get() << endl; //

return 0;

}

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

Дружественная классу функция может быть членом другого класса, или не принадлежать ни к какому классу.

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

5

Соседние файлы в папке pragma once Hard