Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/104: Рейтинг темы: голосов - 104, средняя оценка - 4.83
 Аватар для GAME
23 / 23 / 5
Регистрация: 31.10.2009
Сообщений: 199

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

18.09.2010, 12:27. Показов 19463. Ответов 16
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
У меня есть базовый класс
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);
Оператор вызывался корректно, только А оставалось без изменений....
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
18.09.2010, 12:27
Ответы с готовыми решениями:

Наследование и перегрузка операторов
Помогите, пожалуйста! Ткните носом в ошибки.. не судите строго - первая прога в С++, как и в объектно-ориент программировании: ...

Наследование. Перегрузка операторов
Не понятно, почему компилятор ругается на 49 строку - "отстутствует оператор "++", соответствующий этим операндам". В производном...

ООП в С++ (наследование, инкапсуляция, полиморфизм, перегрузка операторов): что читать?
Нужно освежить, подзабылось. Были у меня институцкие методички доцента Шеховцова. Хороша вещь, но потерялись. Нужны либо набор...

16
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
18.09.2010, 12:57
Может как-то так?

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 минут
нет... не поможет
0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
18.09.2010, 16:04
Цитата Сообщение от 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. Переопределяемые методы хорошо бы делать виртуальными
2
 Аватар для GAME
23 / 23 / 5
Регистрация: 31.10.2009
Сообщений: 199
18.09.2010, 22:37  [ТС]
Nameless One, я попробую ...

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

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

не совсем понял ...
0
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
18.09.2010, 23:53
В данной постановке задачи нет решения. Если мы вызываем внутри сложения saturation оператор +(myfloat, myfloat), то и результат получим myfloat. А способа породить из этого myfloat требуемый для возврата saturation у нас нет.
0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
19.09.2010, 02:32
Цитата Сообщение от 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;
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
19.09.2010, 03:01
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;
};
0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
19.09.2010, 09:20
Цитата Сообщение от Lavroff Посмотреть сообщение
C++
1
2
//...
friend Int operator +(const Int& Ob, const int elem);
Вот здесь как раз-таки дружественный оператор - не обязателен. Да и спецификатор const для типа int.
0
Заблокирован
19.09.2010, 10:06
Nameless One,
Да и спецификатор const для типа int.
наверно const нужен чтобы не произошло изменение операнда, в случае если программист напишет оператор с ошибками
0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
19.09.2010, 10:13
rrrFer, int же передается по значению, а не по ссылке, поэтому ни о каком изменении не может быть и речи
0
Заблокирован
19.09.2010, 10:36
Nameless One, а тогда да, я думал вы про:
C++
1
const Int& Ob
ошибся вобщем
0
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
19.09.2010, 11:24
Цитата Сообщение от 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);
}
1
 Аватар для GAME
23 / 23 / 5
Регистрация: 31.10.2009
Сообщений: 199
19.09.2010, 11:49  [ТС]
Цитата Сообщение от 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));
}
0
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
19.09.2010, 12:53
Конвертируй в ссылки, а не непосредственно в myfloat (у меня там выше показано, как правильно). Ну а при наличии конструктора тебе лучше написать такой плюсик:
C++
1
2
3
4
saturation operator + (const saturation &op1, const saturation &op2)
{
    return static_cast<myfloat&>(op1) + op2;
}
1
 Аватар для GAME
23 / 23 / 5
Регистрация: 31.10.2009
Сообщений: 199
19.09.2010, 13:28  [ТС]
Цитата Сообщение от 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 преобразовать.
0
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
19.09.2010, 14:16
Избежать лишних вызовов конструктора копирования - уже хорошее дело. Ну и при встраивании функций тоже помощь оптимизатору.
Ну а в моём примере надо конвертировать в <const myfloat&>, тогда всё заработает. Но конструктор всё-таки нужен.
1
 Аватар для GAME
23 / 23 / 5
Регистрация: 31.10.2009
Сообщений: 199
19.09.2010, 15:14  [ТС]
Nick Alte, спасибо огромное
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
19.09.2010, 15:14
Помогаю со студенческими работами здесь

Нужен код, в котором есть: Классы, Наследование, Виртуальная функция, Перегрузка операторов
Скоро сдавать лабораторные работы, помогите пожалуйста)) Если можете, пришлите код, в котором есть: Классы, Наследование, Виртуальная...

Множественное наследование, Перегрузка функций, Перегрузка операторов, Использование дружественных функций и классов, Использование шаблонов классов
Здравствуйте!!! Я бы хотел попросить помоч решить...ну или скинуть примеры таких задач, если вдруг у вас они завалялись на компе или...

Что такое "перегрузка операторов"? Каковы принципы работы перегруженных операторов и назначение указателя this
Добрый день . Помогите понять принцип работы перегрузки операторов. объясните пожалуйста в зависимости от чего зависит агрумент при...

Наследование операторов
Пожалуйста, подскажите как правильно задать оператор например =, в базовом классе, а вызывать в классе потомке, на примере: Базовый...

Перегрузка операторов "==" и "!=" для строк
Помогите решить задачу на c++ мучаюсь 3 день Перегрузить операторы «==» и «!=» для строк. Оператор «==» возвращает соответственно 1,...


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

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru