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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.71
Scorpion93
2 / 2 / 0
Регистрация: 31.10.2010
Сообщений: 120
#1

Перезагрузка operator == - C++

13.11.2011, 02:40. Просмотров 1738. Ответов 45
Метки нет (Все метки)

Тренируюсь и пишу клас комплексных чисел. Проблема с перезагнрузкой оператора сравнения да и другие перезагрузки не хотят использоваться. Как решить эту проблему? Ведь желательно передавать константные ссылки? Но к ним уже стает проблематично использовать перезагрузки..

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <math.h>
 
using namespace std;
class MyComplex
{
private:
    double a;
    double b;
public:
    MyComplex(void);
    MyComplex(double,double);
    void ConsoleInput();
    void ConsoleOutput();
    string Output();
    bool operator==(double);
    MyComplex operator +(const MyComplex &);
    MyComplex operator -(const MyComplex &);
    MyComplex operator *(const MyComplex &);
    MyComplex operator /(const MyComplex &);    
    ~MyComplex(void);
};
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
#include "StdAfx.h"
#include "MyComplex.h"
 
 
MyComplex::MyComplex(void): a(0),b(0)
{   
     
}
MyComplex::~MyComplex(void)
{
}
MyComplex::MyComplex(double x,double y):a(x),b(y)
{
}
void MyComplex::ConsoleInput()
{
    
    cout<<"Real:";
    cin>>a;
    cout<<"Imagine:";
    cin>>b; 
}
void MyComplex::ConsoleOutput()
{
    if (b<0) cout<<a<<"-i"<<b;
    if (b==0) cout<<a;
    if (b>0) cout<<a<<"+i"<<b;
    cout<<endl; 
}
string MyComplex::Output()
{
    string s;
    return s;
}
MyComplex MyComplex::operator +(const MyComplex & r)
{
    return MyComplex(a+r.a,b+r.b);
}
MyComplex MyComplex::operator -(const MyComplex & r)
{
    return MyComplex(a-r.a,b-r.b);
}
MyComplex MyComplex::operator *(const MyComplex & r)
{
    return MyComplex(a*r.a-b*r.b,b*r.a+a*r.b);
}
MyComplex MyComplex::operator /(const MyComplex & r)
{
        r==0.0; // тут ошибка: Ошибка   1   error C2678: бинарный "==": не найден оператор, принимающий левый операнд типа "const MyComplex" (или приемлемое преобразование отсутствует)    d:\test\test\mycomplex.cpp  49  1   test
        if (r.a==0 && r.b==0) throw 1; 
        return MyComplex((a*r.a+b*r.b)/(pow(r.a,2)+pow(r.b,2)),(b*r.a-a*r.b)/(pow(r.a,2)+pow(r.b,2)));
}
bool MyComplex::operator==(double zero)
{
    return a==0 && b==0;
}
Добавлено через 2 минуты
И еще вопрос к try catch: Посоветуйте как правильно отловить ошибку с делением на 0.
C++
1
2
3
4
5
6
7
8
9
try
    {
            c=a/b;
            c.ConsoleOutput();
    }
    catch (int a)
    {
        cout<<"Error! Division by zero!"<<endl;
}
вот в мейне присутствует такой код, он работает. Так делать нормально?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.11.2011, 02:40
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Перезагрузка operator == (C++):

Перезагрузка operator - - C++
Есть одна задача : Одномерный массив а и b. Класс одномерный массив. Реализовать для объектов данного класса перезагрузку операции -...

перезагрузка operator + - C++
есть самописный класс String; в нем определены операторы + для, String + String String + char String + *char для вывода в поток и...

Перезагрузка операторов "неоднозначный operator" - C++
Не знаю в ту ли группу пишу, но все же.... Для моего класса есть несколько операторов присвоения const MyStr&amp; operator +=(const MyStr&amp;...

Class & operator's |Error: undefined reference to operator - C++
Компилирует нормально, но когда хочу использовать оператор выдает ошибку:undefined reference to 'operator..(Fraction const&amp;, Fraction...

Вызов operator[] через operator[] const - C++
Перелистывал Майерса, наткнулся на код, подскажите пожалуйста почему он советует закомментированный вариант кода, не проще сделать как...

operator char() или operator int() - C++
Здорова госпдо! Снова ничо не ясно как всегда. Разбираю программку из книги Страуструпа, там он описывает класс String в нем есть ...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Bers
Заблокирован
15.11.2011, 13:55 #16
Цитата Сообщение от silent_1991 Посмотреть сообщение
Эти две фразы не являются эквивалентными.
Тем не менее, это - нарушение инварианта класса. Если он бросит исключение, а вызывающая сторона его не обработает, класс окажется виновником крэша.

А вызывающая сторона не обязана обрабатывать исключения. И даже не обязана знать о них.
Более того, инкапсуляция гарантирует вызывающей стороне, что она имеет право работать с классом через его интерфейс вообще ничего о нем не зная.

Она не обязана знать о кодах ошибок, и она не обязана знать об исключениях. Она вообще не обязана ничего знать об устройстве класса. Только - его публичный интерфейс.


Цитата Сообщение от silent_1991 Посмотреть сообщение
Каким образом вы восстановитесь после ошибки "деление на нуль"?
Не нужно восстанавливаться после ошибки.
Нужно не допускать ошибок.
Нужно заранее спрогнозировать, что получится деление на ноль, и не допустить выполнение такой операции.

Если аргументы не_валидны (их использование приведёт к аварии), то - отказ всей операции. И откат на исходную позицию. Пользователь получает уведомление в виде кода ошибки (если это возможно), либо - любую дефолтную муру + GetLastError() если вернуть код ошибки средствами самого метода не возможно.

В дебаге правомерно бросить ассерт, который не заломает процесс, но высветит предупреждение (если допустим есть подозрение, что вызывающая сторона содержит программную ошибку)

А релизе любой метод, который теоретически может сделать "отказ операции" нужно ВСЕГДА проверять на код ошибки. Конечно, если вызывающая сторона заинтересована в безопасности. Если не заинтересована - тогда не обязательно.

Она может игнорировать сообщения класса, и это не приведёт к крэшу, просто потому, что класс никогда не сделает ничего такого, что может привести к крушению.

Если же крэш происходит на территории вызывающей стороны (допустим класс не выполнил операцию, и вызывающая сторона оказалась неготовой к следующей операции, и эта следующая операция вызвала крэш) - то это уже косяк вызывающей стороны, и программиста, который её делал. Класс тут уже не приделах.

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



Цитата Сообщение от silent_1991 Посмотреть сообщение
Возможно, пользователь имел ввиду 1? Окей, давайте вместо нуля единичку подставим. Стоп. А вдруг он хотел 10?.
С точки зрения самого класса, как самостоятельной целостной логической единицы - совершенно не важно, о чем думала вызывающая сторона, когда присылала упоротые аргументы.
Важно только три вещи:

1. Не допустить крэша по своей вине.
2. Выполнить задачу, которую на класс навесил его создатель.
3. Выполнить штатную процедуру отказа от работы в случае, если выполнение работы противоречит первому пункту.

/зы исключение нарушает инкапсуляцию
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 321
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
15.11.2011, 14:11 #17
Bers,
Если все классы стремятся делать в духе строгой гарантии
Тогда бы не было других гарантий. Но они есть.

Ты слишком жестоко относишься к ислючениям.
silent_1991
Эксперт С++
4963 / 3039 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
15.11.2011, 14:12 #18
Bers, чем деление на нуль отличается от выхода за границы массива?
Bers
Заблокирован
15.11.2011, 14:17 #19
Цитата Сообщение от ForEveR Посмотреть сообщение
Ты слишком жестоко относишься к ислючениям.
1. Они захламляют код, и ухудшают читабельность.
2. Нарушают инкапсуляцию класса.
3. Нарушают инвариант класса.

4. Идеологически - это последний рубеж обороны класса в борьбе за выживаемость системы.
Его следует использовать только тогда, когда очевидно, что класс своими силами не в состоянии справиться с возникшей проблемой, в надежде, что вызывающая сторона сумеет разрулить проблему.

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

Добавлено через 45 секунд
Цитата Сообщение от silent_1991 Посмотреть сообщение
Bers, чем деление на нуль отличается от выхода за границы массива?
Тем что деление на нуль - это деление на нуль.
А выход за пределы массива - это выход за пределы массива
taras atavin
Ушёл с форума.
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
15.11.2011, 14:24 #20
Цитата Сообщение от Bers Посмотреть сообщение
Тем не менее, это - нарушение инварианта класса. Если он бросит исключение, а вызывающая сторона его не обработает, класс окажется виновником крэша.
Но если всё таки исключение необходимо, то придётся его бросить, иначе крах гарантированно будет до того, как кто то что то не обработает, а так хоть какая то надежда на продолжение работы. Но без нужды не кидать.
Bers
Заблокирован
15.11.2011, 14:26 #21
Цитата Сообщение от taras atavin Посмотреть сообщение
Но если всё таки исключение необходимо, то придётся его бросить, иначе крах гарантированно будет до того, как кто то что то не обработает, а так хоть какая то надежда на продолжение работы. Но без нужды не кидать.
Ну дык, о том и речь - что исключение нужно кидать когда случилась исключительная ситуация, а не по малейшему поводу и без повода.
taras atavin
Ушёл с форума.
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
15.11.2011, 14:27 #22
Цитата Сообщение от Bers Посмотреть сообщение
Даже если класс кинул исключение, отловить его и разрулить проблему должна система, к которой принадлежит класс, а не пользователь, который вообще не обязан знать о том, какие, и по какой причине класс может кинуть исключения.
А если проблема в неправильном вводе? Так что это правило тоже надо переписать так: без нужды не говорить пользователю об исключениях.
Bers
Заблокирован
15.11.2011, 14:28 #23
Цитата Сообщение от taras atavin Посмотреть сообщение
А если проблема в неправильном вводе?
Что такое "неправильный ввод" ?
taras atavin
Ушёл с форума.
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
15.11.2011, 14:41 #24
Цитата Сообщение от silent_1991 Посмотреть сообщение
чем деление на нуль отличается от выхода за границы массива?
Деление на ноль - не допустимая математическая операция, а выход за границу массива - недопустимая адресация. Вот представь себе:
1. Ты вычисляешь, сколько залить бензина в бак. Результат не может быть ни бесконечным, ни неопределённым, ни отрицательным, ни имеющим мнимую часть. А ты поделил на ноль. (x/y)*y=x, z*0=0, при любом x<>0, z=x/y, получаем, что при y=0 будет (x/0)*0=x, z*0=x, 0=x, 0<>0. Это не допустимо математически.
2. Ты говоришь таксисту адрес: страна Выдумляндия, область Кисельных Облаков, город Молокореченск, улица Сказочников, дом минус восемь с половиной. Это не существующий адрес, но вычислять его не надо.

Добавлено через 4 минуты
Цитата Сообщение от Bers Посмотреть сообщение
Что такое "неправильный ввод" ?
Это если пользователь ввёл текст вместо числа, ноль на место делителя, отрицательное количество, не существующее имя файла, или ещё какие невалидные данные и сделал это вручную.
Bers
Заблокирован
15.11.2011, 14:45 #25
Цитата Сообщение от taras atavin Посмотреть сообщение
Например, пользователь ввёл текст вместо числа, ноль на место делителя, отрицательное количество, не существующее имя файла, или ещё какие невалидные данные и сделал это вручную.
"извините, ожидалось число, а не текст. Введите данные заного"
"извините, но делитель нулем быть не может. введите другой делитель"
и тп.

это ШТАТНАЯ работа любого морального терминала - проверить что введёт пользователь.
Накой чорт тут вообще может понадобится бросать исключения? Кто их будит обрабатывать? Блондинка, которая тыкает в сенсорный экранчик терминала, пытаясь внести деньги на счет?
silent_1991
Эксперт С++
4963 / 3039 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
15.11.2011, 14:46 #26
Цитата Сообщение от Bers Посмотреть сообщение
1. Они захламляют код, и ухудшают читабельность.
Конечно, не то, что возврат результат выполнения и кода ошибки в одно и том же месте...
Цитата Сообщение от Bers Посмотреть сообщение
2. Нарушают инкапсуляцию класса.
Каким образом?
Цитата Сообщение от Bers Посмотреть сообщение
3. Нарушают инвариант класса.
Это и без исключений можно сделать. Всё от прямоты рук зависит.
Цитата Сообщение от Bers Посмотреть сообщение
4. Идеологически - это последний рубеж обороны класса в борьбе за выживаемость системы.
Его следует использовать только тогда, когда очевидно, что класс своими силами не в состоянии справиться с возникшей проблемой, в надежде, что вызывающая сторона сумеет разрулить проблему.
Подо всё это сильно-сильно подходит деление на нуль.
Цитата Сообщение от Bers Посмотреть сообщение
5. Даже если класс кинул исключение, отловить его и разрулить проблему должна система, к которой принадлежит класс, а не пользователь, который вообще не обязан знать о том, какие, и по какой причине класс может кинуть исключения.
А кто-то говорит, что это должно вернуться непременно пользователю?
Bers
Заблокирован
15.11.2011, 14:50 #27
Цитата Сообщение от silent_1991 Посмотреть сообщение
Каким образом?
Вынуждает пользователей знать внутренее устройство класса. Знать когда, какие, и по какой причине он может кинуть исключения. ЗАСТАВЛЯЕТ пользователя строить ловушки исключений, потому что класс тупо спихивает отвественность за крэш на пользователя. То, как быть и как разруливать ситуацию придётся решать пользователю. Пользователю придётся познать природу возможных исключений, познать то, что приводит к ним, что бы понять как их можно обработать.

Это при том, что инкапсуляция гарантирует пользователю, что он может пользоваться классом ничего не зная о его устройстве.

Итого: нарушение инкапсуляции.
silent_1991
Эксперт С++
4963 / 3039 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
15.11.2011, 14:51 #28
Цитата Сообщение от Bers Посмотреть сообщение
Кто их будит обрабатывать? Блондинка, которая тыкает в сенсорный экранчик терминала, пытаясь внести деньги на счет?
Что за бред?
Bers
Заблокирован
15.11.2011, 14:53 #29
Цитата Сообщение от silent_1991 Посмотреть сообщение
Что за бред?
сабж:

Цитата Сообщение от taras atavin Посмотреть сообщение
Это если пользователь ввёл текст вместо числа, ноль на место делителя, отрицательное количество, не существующее имя файла, или ещё какие невалидные данные и сделал это вручную.
silent_1991
Эксперт С++
4963 / 3039 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
15.11.2011, 14:55 #30
Цитата Сообщение от Bers Посмотреть сообщение
Вынуждает пользователей знать внутренее устройство класса
Это с чего бы вдруг?
Цитата Сообщение от Bers Посмотреть сообщение
Знать когда, какие, и по какой причине он может кинуть исключения
А это он обязан знать, иначе нормальной работы с классом не будет.
Цитата Сообщение от Bers Посмотреть сообщение
класс тупо спихивает отвественность за крэш на пользователя
А на кого ему спихивать ответственность (учтём, что вместо "пользователь" стоит читать "вызывающая сторона"). Что ему делать, если пришли невалидные данные? Надеяться, что их кто-та там раньше обработал? А если нет? Падать в рантайме? Кул.
Цитата Сообщение от Bers Посмотреть сообщение
Это при том, что инкапсуляция гарантирует пользователю, что он может пользоваться классом ничего не зная о его устройстве.
Исключения ну никак с внутренним устройством класса не связаны.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.11.2011, 14:55
Привет! Вот еще темы с ответами:

Реализация operator + через operator += - C++
внутри следующей темы возник вопрос, ответ на который так и не был получен: ...

Перегрузить операторы operator+() и operator*() в пользовательском классе "Комплексное число" - C++
Здравствуйте. Предлагаю заняться арифметикой. Создал прослейший класс, перегрузил операторы сложения и умножения, в конструкторе...

Operator +, operator += — какой через какой реализовывать? - C++
Для class Fraction { // ... public: Fraction operator + ( const Fraction&amp; right ) const; Fraction&amp; operator += ( const...

Чем "operator *=" отличается от "operator *"? - C++
снова застряла, не могу понять, чем этот оператор должен отличаться от оператора*.....? вот он, но это работает только в случае...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
15.11.2011, 14:55
Закрытая тема Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru