Форум программистов, компьютерный форум CyberForum.ru

Как же все-таки лучше всего перегружать операторы? - C++

Восстановить пароль Регистрация
 
gore-lykovoe
 Аватар для gore-lykovoe
31 / 31 / 1
Регистрация: 04.04.2010
Сообщений: 414
08.09.2013, 01:31     Как же все-таки лучше всего перегружать операторы? #1
1. Нужно ли использовать friend там, где это возможно? (или не стоит злоупотреблять где-нибудь?)
2. Стоит ли при перегрузке бинарного оператора "+" делать его обособленным от класса?
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
// свободная ф-ия которая не friend для класса DATES
// она просто использует публичный оператор operator +=
DATES operator + (const DATES& lhs, const DATES& rhs)
{
  DATES result(lhs);
  result += rhs; // заиспользовали публичный оператор +=
  return result;
}


Оператор присваивания и копирующий конструктор обсуждать не нужно - с ними все понятно.

Интересно ваше мнение насчет перегрузок взятых из статьи на хабре:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
class Integer
{
private:
    int value;
public:
    Integer(int i): value(i) 
    {}
 
    //унарный +
    friend const Integer& operator+(const Integer& i);
 
    //унарный -
    friend const Integer operator-(const Integer& i);
 
    //префиксный инкремент
    friend const Integer& operator++(Integer& i);
 
    //постфиксный инкремент
    friend const Integer operator++(Integer& i, int);
 
    //префиксный декремент
    friend const Integer& operator--(Integer& i);
 
    //постфиксный декремент
    friend const Integer operator--(Integer& i, int);
};
 
//унарный плюс ничего не делает.
const Integer& operator+(const Integer& i) {
    return i.value;
}
 
const Integer operator-(const Integer& i) {
    return Integer(-i.value);
}
 
//префиксная версия возвращает значение после инкремента
const Integer& operator++(Integer& i) {
    i.value++;
    return i;
}
 
//постфиксная версия возвращает значение до инкремента
const Integer operator++(Integer& i, int) {
    Integer oldValue(i.value);
    i.value++;
    return oldValue;
}
 
//префиксная версия возвращает значение после декремента
const Integer& operator--(Integer& i) {
    i.value--;
    return i;
}
 
//постфиксная версия возвращает значение до декремента
const Integer operator--(Integer& i, int) {
    Integer oldValue(i.value);
    i.value--;
    return oldValue;
}
 
class Integer
{
private:
    int value;
public:
    Integer(int i): value(i) 
    {}
    friend const Integer operator+(const Integer& left, const Integer& right);
 
    friend Integer& operator+=(Integer& left, const Integer& right);
 
    friend bool operator==(const Integer& left, const Integer& right);
};
 
const Integer operator+(const Integer& left, const Integer& right) {
    return Integer(left.value + right.value);
}
 
Integer& operator+=(Integer& left, const Integer& right) {
    left.value += right.value;
    return left;
}
 
bool operator==(const Integer& left, const Integer& right) {
    return left.value == right.value;
}
 
[url]http://habrahabr.ru/post/132014/[/url]


Со всеми ли моментами вы согласны? Просто у меня много сомнений. Например, зачем использовать при перегрузке постфиксного и префиксного инкремента\декремента в аргументе объект класса. Ведь прекрасно перегружается и без него. Может стоит делать логические операторы свободными?

Вообщем хочется делать всё как лучше и искренне надеюсь, что не получится как всегда.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.09.2013, 01:31     Как же все-таки лучше всего перегружать операторы?
Посмотрите здесь:

Как лучше всего хранить коэффициенты? C++
C++ Как лучше всего учить язык C++?
Для енама нельзя перегружать операторы? C++
какие операторы нельзя перегружать? C++
Как лучше всего создать форму в С++ C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
xtorne21st
интересующийся
300 / 271 / 19
Регистрация: 25.09.2010
Сообщений: 1,056
08.09.2013, 02:06     Как же все-таки лучше всего перегружать операторы? #2
friend использовать - считается плохим стилем разработки программного продукта. Они должны появиться в проекте через год, два - от безисходности.
gore-lykovoe
 Аватар для gore-lykovoe
31 / 31 / 1
Регистрация: 04.04.2010
Сообщений: 414
08.09.2013, 02:09  [ТС]     Как же все-таки лучше всего перегружать операторы? #3
Цитата Сообщение от xtorne21st Посмотреть сообщение
friend использовать - считается плохим стилем разработки программного продукта. Они должны появиться в проекте через год, два - от безисходности.
Вы наверное говорите о классах. А я об операторах.
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
08.09.2013, 02:27     Как же все-таки лучше всего перегружать операторы? #4
Цитата Сообщение от gore-lykovoe Посмотреть сообщение
Стоит ли при перегрузке бинарного оператора "+" делать его обособленным от класса?
стоит.
Цитата Сообщение от gore-lykovoe Посмотреть сообщение
Нужно ли использовать friend там, где это возможно?
нет.

если перегруженный оператор меняет состояние объекта для которого он вызывается - перегружаем его как мембер, если не меняет - как свободную функцию.
правильная перегрузка оператора + не меняет состояние объектов для которых вызывается, потому её лучше делать независимой.
правильная перегрузка оператора += меняет состояние объекта для которого вызывается, потому её лучше сделать мембером класса.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
08.09.2013, 03:00     Как же все-таки лучше всего перегружать операторы? #5
Солтер Н.А., Клепер С.Дж. С++ для профессионалов.
Миниатюры
Как же все-таки лучше всего перегружать операторы?   Как же все-таки лучше всего перегружать операторы?   Как же все-таки лучше всего перегружать операторы?  

Mr.X
Эксперт С++
 Аватар для Mr.X
2807 / 1583 / 248
Регистрация: 03.05.2010
Сообщений: 3,692
08.09.2013, 07:33     Как же все-таки лучше всего перегружать операторы? #6
Ну, основную причину, по которой используются дружественные перегруженные операторы никто так и не назвал. А она проста – это неявное преобразование типов аргументов. Например, если бы в шаблоне std::complex перегруженный оператор сложения был бы функцией-членом, мы не смогли бы прибавить к действительному числу комплексное.
gore-lykovoe
 Аватар для gore-lykovoe
31 / 31 / 1
Регистрация: 04.04.2010
Сообщений: 414
08.09.2013, 11:32  [ТС]     Как же все-таки лучше всего перегружать операторы? #7
А стоит ли добавлять inline к перегрузкам?
monolit
179 / 179 / 21
Регистрация: 24.03.2011
Сообщений: 641
Завершенные тесты: 1
08.09.2013, 12:23     Как же все-таки лучше всего перегружать операторы? #8
Я искренне не понимаю, почему инкремент и декремент сделаны дружественными, а не функциями класса. Никакого профита от этого не вижу, да и текста больше, чем могло бы быть...
xtorne21st
интересующийся
300 / 271 / 19
Регистрация: 25.09.2010
Сообщений: 1,056
08.09.2013, 13:20     Как же все-таки лучше всего перегружать операторы? #9
Цитата Сообщение от monolit Посмотреть сообщение
Я искренне не понимаю, почему инкремент и декремент сделаны дружественными, а не функциями класса. Никакого профита от этого не вижу, да и текста больше, чем могло бы быть...
Для того, чтобы не захламльть класс вспомогательными функциями, без которых, по сути можно и обойтись. Класс должен включать в себя минимильный для функционирования набор методов. Так и код в дальнейшем читать легче и модифицировать класс. Если всёже хотите как-то выделить ваш класс и прилагающие к нему функции/операторы, на фоне другого кода, можно просто обвернуть "это всё дело" в неимспейсы.
gore-lykovoe
 Аватар для gore-lykovoe
31 / 31 / 1
Регистрация: 04.04.2010
Сообщений: 414
08.09.2013, 14:25  [ТС]     Как же все-таки лучше всего перегружать операторы? #10
Цитата Сообщение от xtorne21st Посмотреть сообщение
Для того, чтобы не захламльть класс вспомогательными функциями, без которых, по сути можно и обойтись.
так эти функции и не нужны
плюс, как уже сказали:
Цитата Сообщение от Jupiter Посмотреть сообщение
если перегруженный оператор меняет состояние объекта для которого он вызывается - перегружаем его как мембер
а префиксный инкремент и декрмент как-раз изменяют состояние объекта, да и скрины из книги показывают, что friend не нужен, я лучше доверюсь своему чутью, книгам, опытным пользователям этого форума, чем какому-то учителю, написавшему статью на хабре, где никто не имеет своего мнения, лишь бы им не слили карму...

Добавлено через 15 минут
Побыстрому написал перегрузки, чтобы запомнить, всё ли правильно? Или что-нибудь лучше сделать по-другому?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <iostream>
class Integer
{
    int p;
public:
    int get(void) { return p; }
    void add(int pp) { p+=pp; }
    Integer(int pp) { p=pp; }
    // перегрузка операторов
    Integer(const Integer&);
    // унарные операторы
    Integer& operator= (const Integer&);
    const Integer operator+ () const;
    const Integer operator- () const;
    Integer& operator+= (const Integer&);
    Integer& operator-= (const Integer&);
    Integer& operator++ ();
    const Integer operator++ (int);
    Integer& operator-- ();
    const Integer operator-- (int);
    // операторы ввода/вывода
    friend std::ostream &operator<< (std::ostream&, const Integer&);
    friend std::istream &operator>> (std::istream&, Integer&);
    // операторы сравнения
    friend bool operator == (const Integer&, const Integer&);
    friend bool operator < (const Integer&, const Integer&);
};
// перегрузка копирующего конструктора
Integer::Integer(const Integer& obj)
{
    p=obj.p;
}
// перегрузка присваивания
Integer& Integer::operator= (const Integer& obj)
{
    if (this != &obj)
        p=obj.p;
    return *this;
}
// перегрузка унарного +
const Integer Integer::operator+ () const
{
    return Integer(p);
}
// перегрузка унарного -
const Integer Integer::operator- () const
{
    return Integer(-p);
}
// перегрузка арифметического присваивания +=
Integer& Integer::operator+= (const Integer& obj)
{
    p+= obj.p;
    return *this;
}
// перегрузка арифметического присваивания -=
Integer& Integer::operator-= (const Integer& obj)
{
    p-= obj.p;
    return *this;
}
// перегрузка префиксного инкремента
Integer& Integer::operator++ ()
{
    p++;
    return *this;
}
// перегрузка постфиксного инкремента
const Integer Integer::operator++ (int)
{
    return Integer(++p);
}
// перегрузка префиксного декремента
Integer& Integer::operator-- ()
{
    p--;
    return *this;
}
// перегрузка постфиксного декремента
const Integer Integer::operator-- (int)
{
    return Integer(--p);
}
 
// БИНАРНЫЕ ОПЕРАТОРЫ
// перегрузка сложения
Integer operator+ (const Integer left, const Integer right)
{
    Integer rez(left);
    rez+=right;
    return rez;
}
// перегрузка вычетания
Integer operator- (const Integer left, const Integer right)
{
    Integer rez(left);
    rez-=right;
    return rez;
}
// перегрузка ввода/вывода
std::ostream &operator<< (std::ostream& out, const Integer& obj)
{
    out<<obj.p;
    return out;
}
std::istream &operator>> (std::istream& in, Integer& obj)
{
    in>>obj.p;
    return in;
}
// перегрузка логических операторов
bool operator == (const Integer& obj1, const Integer& obj2)
{
    return (obj1.p==obj2.p);
}
bool operator < (const Integer& obj1, const Integer& obj2)
{
    return (obj1.p<obj2.p);
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.09.2013, 14:38     Как же все-таки лучше всего перегружать операторы?
Еще ссылки по теме:

C++ Нужен совет: как лучше всего сгенерировать документ .doc с оформлением по ГОСТу
C++ Подскажите, как лучше всего изучать язык, ежели в академии не дают достаточный объем знаний
Как лучше всего разделить строку на несколько подстрок? C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
08.09.2013, 14:38     Как же все-таки лучше всего перегружать операторы? #11
Цитата Сообщение от gore-lykovoe Посмотреть сообщение
const Integer operator+ () const;
const Integer operator- () const;
глобальные

перепутал, это унарные, пардон

Цитата Сообщение от gore-lykovoe Посмотреть сообщение
friend bool operator == (const Integer&, const Integer&);
friend bool operator < (const Integer&, const Integer&);
зачем тут friend? у тебя есть метод get(). оператор вывода аналогично, а если добавить ещё метод set то и оператор ввода.
Yandex
Объявления
08.09.2013, 14:38     Как же все-таки лучше всего перегружать операторы?
Ответ Создать тему
Опции темы

Текущее время: 21:36. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru