- •Дружественные функции и перегрузка операций. Преобразование данных.
- •Преобразование, определяемые классом
- •Перегрузка и выбор функции
- •Дружественные функции
- •Перегружаемые операции
- •Перегрузка унарного оператора
- •Перегрузка бинарного оператора
- •Перегружаемые оператор присваивания и индексированные операторы
- •Присваивание против инициализации
Перегрузка бинарного оператора
Если бинарный оператор перегружается с помощью функции-члена, то в качестве своего первого аргумента он получает неявно переданную переменную класса, а второго - единственный из списка аргументов. При объявлении friend-функции или обычной функции в списке параметров определяют оба аргумента.
class clock {
friend clock operator+(const clock &c1,const clock &c2) ;
};
clock operator+(const clock &c1,const clock &c2) {
clock temp(c1.sec+c2.sec); return temp;
}
Оба параметра явно определяются и являются кандидатами для преобразования назначением. Используя это определение имеем:
int i=5; clock c(100);
c+i; // допустимо: i - преобразуется в clock
i+c; // допустимо: i - преобразуется в clock
В противоположность этому, перегрузим двухместный - функцией-членом.
class clock {
clock operator -(const clock &c) { clock temp(sec-c.sec); return temp; }
};
Существует первый неявный аргумент. В него попадает некоторый используемый параметр. Это может вызвать асимметричное поведение двухместных операторов.
int i=5; clock c(100);
c-i; // допустимо i преобразуется в clock; c.operator-(i)
i-c; // недопустимо i не относится к типу clock; i.operator-(c)
Определим операцию умножения: long и clock
clock operator *(long m, const clock &c) {
clock temp(m*c.sec); return temp;
Такая реализация вынуждает операцию умножения иметь фиксированный порядок выполнения, зависящий от типа. Для избежания этого обычно пишется второй перегруженный функциональный оператор.
clock operator *(const clock &c,long m) {
clock temp(m*c.sec); return temp;
}
y@x интерпретируется как y.opertor@(x), если operator @ - функция-член и operator@(y,x), если operator @ - дружественная функция.
Операция вызова функции
Операция вызова функции должна быть объявлена как нестатическая функция-член класса. Она позволяет пользователю определять число операндов.
class X {
int a,b,c;
public:
X(int a1, int b1, int c1): a(a1),b(b1),c(c1) {}
void operator() { int i,int j, int k);
};
X ex(8,20,17); // Вызывается конструктор
ex(10,15,57); // Вызывается операция ()
Перегруженные операции - функции-члены против дружественных функций
Если перегруженная операция реализована как функция-член, то ей либо вообще не передаются явно параметры, либо передается один параметр. Дружественной функции - перегруженной операции - передается один, либо два параметра. Если бинарная операция перегружена как функция-член, то ее первым операндом является объект, который принимает сообщение. Следовательно, явно передается только один параметр. Если унарная перегруженная операция реализована как функция-член, то ее операндом является принимающий сообщение объект. Таким образом, эта функция-член не имеет явных параметров. Перегруженная операция не может иметь более двух параметров.
Фунция-член Class X { X operator-() const; // Унарный минус X operator&() const; // Вычисление адреса X operator^() const; // Ошибка: операция ^ -бинарная }; |
Дружественная функция class Y { friend Y operator-(const Y&); friend Y operator&(const Y&); freind Y operator^(const Y&); }; |
Class X { X operator-(const X&) const; // бинрный минус X operator&( const X&) const; // побитовое И }; |
class Y { friend Y operator-(const Y&,const Y&); friend Y operator&(const Y&, const Y&); }; |