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

Наследование и перегрузка операторов. - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 48, средняя оценка - 4.75
GAME
 Аватар для GAME
22 / 22 / 3
Регистрация: 31.10.2009
Сообщений: 199
18.09.2010, 12:27     Наследование и перегрузка операторов. #1
У меня есть базовый класс
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class myfloat
{
protected:
    int c;
    int z;
    void reduce();
public:
    myfloat(float num=0);
    myfloat(int i,int j);
    void print();
    friend myfloat operator+(myfloat,myfloat);
    friend myfloat operator-(myfloat,myfloat);
    friend myfloat operator*(myfloat,myfloat);
    friend myfloat operator/(myfloat,myfloat);
};
И есть второй класс, который открыто наследует myfloat
C++
1
2
3
4
5
6
7
8
9
10
11
12
class saturation:public myfloat
{
    bool flag;
    void CheckLimit();
public:
    saturation(float=0);
    void show();
    friend saturation operator+(saturation,saturation);
    friend saturation operator-(saturation,saturation);
    friend saturation operator*(saturation,saturation);
    friend saturation operator/(saturation,saturation);
};
Проблема заключается вот в чём:
нужно в производном классе saturation написать операторы.
выглядеть они должны так.
(например оператор +)
C++
1
2
3
4
5
6
saturation operator+(saturation A,saturation B)
{
    //ВЫЗОВ ОПЕРАТОРА + ИЗ КЛАССА myfloat
    //ВЫЗОВ Функции CheckLimit() из класса saturation для A, судя по всему-   A.CheckLimit();
    return /* Что-то */;
}
в классе myfloаt все операторы написаны
пробовал вызывать оператор + из mfloat вот так :
C++
1
myfloat(A)=operator +((myfloat)A,(myfloat)B);
Оператор вызывался корректно, только А оставалось без изменений....
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.09.2010, 12:27     Наследование и перегрузка операторов.
Посмотрите здесь:

Перегрузка операторов C++
Перегрузка операторов. C++
Наследование и перегрузка операторов C++
Перегрузка операторов C++
C++ Перегрузка операторов
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
18.09.2010, 12:57     Наследование и перегрузка операторов. #2
Может как-то так?

C++
1
2
3
4
5
6
saturation operator+(saturation& A, saturation& B)
{
   saturation C;
   static_cast<myfloat>(C)=static_cast<myfloat>(A)+static_cast<myfloat>(B);
   return C;
}
Добавлено через 15 минут
нет... не поможет
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
18.09.2010, 16:04     Наследование и перегрузка операторов. #3
Цитата Сообщение от GAME Посмотреть сообщение
Оператор вызывался корректно, только А оставалось без изменений....
Наверно потому, что объект в левой части выражения - это временный объект, созданный на основе объекта A?

Кстати, а какая необходимость была объявлять операторы дружественными?
Вот пример, как можно было бы сделать:
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
#include <iostream>
 
class base
{
 
public:
    
    base(int x)
        : _x(x) {}
        
    base(const base& rhs)
        : _x(rhs._x) {}
        
    virtual base operator + (const base& rhs)
    {
        base b(_x + rhs._x);
        return b;
    }
    
    virtual void show()
    {
        std::cout << _x << std::endl;
    }
    
protected:
    
    int _x;
};
 
class derived: public base
{
    
public:
    
    derived(int x, bool f)
        : base(x), _flag(f) {}
        
    derived(const derived& rhs)
        : base(rhs._x), _flag(rhs._flag) {}
        
    derived(const base& rhs)
        : base(rhs), _flag(DEFAULT_FLAG) {}
        
    void setFlag(bool f)
    {
        _flag = f;
    }
        
    operator base()
    {
        return base(_x);
    }
    
    derived operator + (const derived& rhs)
    {
        derived d = static_cast<base>(*this) + static_cast<base>(rhs);
        d.setFlag(_flag | rhs._flag);
        return d;
    }
    
    void show()
    {
        if(_flag)
            base::show();
    }
    
private:
 
    bool _flag;
    const static bool DEFAULT_FLAG = false;
};
 
int main()
{
    derived d1(3, false), d2(2, true), d3 = d1 + d2;
    d3.show();
    return 0;
}
PS. Переопределяемые методы хорошо бы делать виртуальными
GAME
 Аватар для GAME
22 / 22 / 3
Регистрация: 31.10.2009
Сообщений: 199
18.09.2010, 22:37  [ТС]     Наследование и перегрузка операторов. #4
Nameless One, я попробую ...

насчёт виртуальных функций - нельзя их юзать по тех.заданию
и класс myfloat тоже нельзя изменять....
насчёт дружественных фун-й незнаю ... )))

Добавлено через 15 минут
Цитата Сообщение от Nameless One Посмотреть сообщение
Наверно потому, что объект в левой части выражения - это временный объект, созданный на основе объекта A?

не совсем понял ...
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
18.09.2010, 23:53     Наследование и перегрузка операторов. #5
В данной постановке задачи нет решения. Если мы вызываем внутри сложения saturation оператор +(myfloat, myfloat), то и результат получим myfloat. А способа породить из этого myfloat требуемый для возврата saturation у нас нет.
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
19.09.2010, 02:32     Наследование и перегрузка операторов. #6
Цитата Сообщение от Nick Alte Посмотреть сообщение
В данной постановке задачи нет решения. Если мы вызываем внутри сложения saturation оператор +(myfloat, myfloat), то и результат получим myfloat. А способа породить из этого myfloat требуемый для возврата saturation у нас нет.
А чем плохо мое решение? Нужно определить оператор приведения типа к base и конструктор, который создает объект derived на основе base, а остальные поля производного класса проинициализировать вручную.

Цитата Сообщение от GAME Посмотреть сообщение
насчёт дружественных фун-й незнаю ... )))
Пример оправданного введения дружественного оператора - это перегрузка оператора вывода в поток:
C++
1
friend std::ostream operator << (std::ostream& os, const base& rhs);
Так как первый операнд оператора - это объект класса std::ostream, то по идее мы должны были определить этот оператор как нибудь так внутри класса std::ostream:
C++
1
ostream& operator << (const base& rhs);
Но std::ostream - это уже существующий класс, и доопределять его мы не можем. Поэтому мы и определяем этот оператор как дружественный.


Цитата Сообщение от GAME Посмотреть сообщение
и класс myfloat тоже нельзя изменять....
И не надо. Как я сказал выше, достаточно в производном классе определить оператор приведения типа к объекту базового класса и создать конструктор, который принимает в качестве аргумента объект базового класса, а поля, которые специфичны для производного класса (у меня это _flag) - проинициализировать вручную
Цитата Сообщение от GAME Посмотреть сообщение
не совсем понял ...
Цитата Сообщение от GAME Посмотреть сообщение
myfloat(A)=operator +((myfloat)A,(myfloat)B);
Что стоит в левой части выражения? myfloat(A) - это вызов копирующего конструктора для объекта класса myfloat. Т.е. создается новый объект класса myfloat на основе A (т.е. это его копия), но этот объект ничему не присваивается и уничтожается после точки с запятой. Правильней уже было бы сделать так:
C++
1
myfloat C = A + B;
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
19.09.2010, 03:01     Наследование и перегрузка операторов. #7
Nameless One, А так же, если нам важен порядок операндов.

C++
1
2
3
4
5
6
7
8
9
10
11
class Int
{
public:
    Int(){}
    ~Int(){}
    Int operator +(const Int&Ob);
    friend Int operator +(const Int& Ob, const int elem);
    friend Int operator +(const int elem, const Int& Ob);
protected:
    int i;
};
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
19.09.2010, 09:20     Наследование и перегрузка операторов. #8
Цитата Сообщение от Lavroff Посмотреть сообщение
C++
1
2
//...
friend Int operator +(const Int& Ob, const int elem);
Вот здесь как раз-таки дружественный оператор - не обязателен. Да и спецификатор const для типа int.
rrrFer
Заблокирован
19.09.2010, 10:06     Наследование и перегрузка операторов. #9
Nameless One,
Да и спецификатор const для типа int.
наверно const нужен чтобы не произошло изменение операнда, в случае если программист напишет оператор с ошибками
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
19.09.2010, 10:13     Наследование и перегрузка операторов. #10
rrrFer, int же передается по значению, а не по ссылке, поэтому ни о каком изменении не может быть и речи
rrrFer
Заблокирован
19.09.2010, 10:36     Наследование и перегрузка операторов. #11
Nameless One, а тогда да, я думал вы про:
C++
1
const Int& Ob
ошибся вобщем
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
19.09.2010, 11:24     Наследование и перегрузка операторов. #12
Цитата Сообщение от Nameless One Посмотреть сообщение
А чем плохо мое решение?
Я не говорю, что оно плохо, но оно как раз изменяет условия, изменяет изначально заданный интерфейс. То же самое имел в виду и я: необходимы небольшие, но продуманные изменения в интерфейсе (введение конструктора из базового типа), которые делают задачу тривиальной.

Добавлено через 10 минут
Традиционные рекомендации для перегрузки арифметических операторов таковы:
а) Делайте операторы членами класса.
б) Переопределяйте в первую очередь операторы, связанные с присваиванием (+=, *= и т.д.)
в) Основные операторы (+, -, *, /) реализуются через то, что сделано в б)
г) Операторы из предыдущего пункта не изменяют первый операнд, поэтому делаются как const; операторы из б) неконстантны.
д) Операторы из б) возвращают ссылку на изменённый первый операнд, основные операторы возвращают новое значение через стек.
Пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MyInt{
public:
    MyInt(int value=0): v(value) {}
    MyInt& operator += (const MyInt& op2) 
    {
        v += op2.v;                                 // Добавляем второй операнд
        return *this;                                // Возвращаем ссылку на первый операнд
    }
    MyInt operator + (const MyInt& op2) const
    {
        MyInt returnValue(*this);  // Создаём новый объект MyInt, копируя данные из первого операнда
        returnValue += op2;         // Прибавляем второй операнд
        return returnValue;          // Возвращаем по значению
    }
private:
    int v;
};
Добавлено через 14 минут
Теперь, если мы посчитаем, что операторы в myfloat и saturation реализованы в соответствии с рекомендациями, достаточно ввести конструктор, порождающий saturation от myfloat:
C++
1
saturation::saturation(const myfloat &src, bool flag_=false): myfloat(src), flag(flag_) {}
И вот в таких условиях можно вообще уже не перегружать арифметические операторы в saturation, если от них нам нужна только та функциональность, что уже есть в myfloat. Ну а если нам надо по результатам операции устанавливать флаг, то это можно реализовать примерно так:
C++
1
2
3
4
5
6
7
8
9
10
11
saturation& saturation::operator += (const saturation& op2)
{
    static_cast<myfloat&>(*this) += op2;
    flag = true;
    return *this;
}
 
saturation saturation::operator + (const saturation& op2) const
{
    return saturation(static_cast<myfloat&>(*this)+op2, true);
}
GAME
 Аватар для GAME
22 / 22 / 3
Регистрация: 31.10.2009
Сообщений: 199
19.09.2010, 11:49  [ТС]     Наследование и перегрузка операторов. #13
Цитата Сообщение от Nameless One Посмотреть сообщение
А чем плохо мое решение? Нужно определить оператор приведения типа к base и конструктор, который создает объект derived на основе base, а остальные поля производного класса проинициализировать вручную.
Да, спасибо, это сработало )

Цитата Сообщение от Nick Alte Посмотреть сообщение
Традиционные рекомендации для перегрузки арифметических операторов таковы:
Полезная информация, учту на будущее. А в этой ситуации сказали делать френдами - сделал )

В итоге в класс sturation добавил конструтор
C++
1
2
3
4
5
saturation::saturation(myfloat num):myfloat(num)
{
    flag=0;
    CheckLimit();
}
Операторы выглядят так
C++
1
2
3
4
saturation operator+(saturation A,saturation B)
{
    return saturation(static_cast<myfloat>(A)+static_cast<myfloat>(B));
}
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
19.09.2010, 12:53     Наследование и перегрузка операторов. #14
Конвертируй в ссылки, а не непосредственно в myfloat (у меня там выше показано, как правильно). Ну а при наличии конструктора тебе лучше написать такой плюсик:
C++
1
2
3
4
saturation operator + (const saturation &op1, const saturation &op2)
{
    return static_cast<myfloat&>(op1) + op2;
}
GAME
 Аватар для GAME
22 / 22 / 3
Регистрация: 31.10.2009
Сообщений: 199
19.09.2010, 13:28  [ТС]     Наследование и перегрузка операторов. #15
Цитата Сообщение от Nick Alte Посмотреть сообщение
Конвертируй в ссылки, а не непосредственно в myfloat (у меня там выше показано, как правильно).

ааааа !! точно !! это всё решает )) тогда можно было бы и без конструктора вообще обойтись )

спасибо ))

И ещё вопросик.
А зачем в оператор передавать ссылки ? мы ведь не будем изменять не op1 не op2 ?
или это нужно для того, чтобы конструктор копирования не вызывать лишний раз ?

Добавлено через 6 минут
Цитата Сообщение от Nick Alte Посмотреть сообщение
Ну а при наличии конструктора тебе лучше написать такой плюсик:

Получилось только так
C++
1
2
3
4
saturation operator+(const saturation &A,const saturation &B)
{
    return static_cast<myfloat>(A)+static_cast<myfloat>(B);
}
При конвертации в ссылки<myfloat&> пишет что нельзя const преобразовать.
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
19.09.2010, 14:16     Наследование и перегрузка операторов. #16
Избежать лишних вызовов конструктора копирования - уже хорошее дело. Ну и при встраивании функций тоже помощь оптимизатору.
Ну а в моём примере надо конвертировать в <const myfloat&>, тогда всё заработает. Но конструктор всё-таки нужен.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.09.2010, 15:14     Наследование и перегрузка операторов.
Еще ссылки по теме:

Перегрузка операторов C++
Наследование операторов C++
C++ Перегрузка операторов + и =

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

Или воспользуйтесь поиском по форуму:
GAME
 Аватар для GAME
22 / 22 / 3
Регистрация: 31.10.2009
Сообщений: 199
19.09.2010, 15:14  [ТС]     Наследование и перегрузка операторов. #17
Nick Alte, спасибо огромное
Yandex
Объявления
19.09.2010, 15:14     Наследование и перегрузка операторов.
Ответ Создать тему
Опции темы

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