Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.50/10: Рейтинг темы: голосов - 10, средняя оценка - 4.50
Scorpion93
2 / 2 / 3
Регистрация: 31.10.2010
Сообщений: 120
#1

Перезагрузка operator ==

13.11.2011, 02:40. Просмотров 1859. Ответов 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;
}
вот в мейне присутствует такой код, он работает. Так делать нормально?

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.11.2011, 02:40
Ответы с готовыми решениями:

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

Перезагрузка operator -
Есть одна задача : Одномерный массив а и b. Класс одномерный массив....

Перезагрузка операторов "неоднозначный operator"
Не знаю в ту ли группу пишу, но все же.... Для моего класса есть несколько...

Class & operator's |Error: undefined reference to operator
Компилирует нормально, но когда хочу использовать оператор выдает...

operator char() или operator int()
Здорова госпдо! Снова ничо не ясно как всегда. Разбираю программку из книги...

45
silent_1991
Эксперт С++
5007 / 3067 / 270
Регистрация: 11.11.2009
Сообщений: 7,043
Завершенные тесты: 1
13.11.2011, 08:18 #2
C++
1
bool operator==(double) const;
C++
1
2
3
4
bool MyComplex::operator==(double zero) const
{
        return a==0 && b==0;
}
Правда не совсем понятно, что это за оператор == такой, который тру возвращает, только если комплексное число нулевое... Но это на вашей совести остаётся.

Цитата Сообщение от Scorpion93 Посмотреть сообщение
Так делать нормально?
Да не особо...
Напишите свой класс-исключение, унаследованный от std::exception, и ловите ссылку на его объект.
1
Scorpion93
2 / 2 / 3
Регистрация: 31.10.2010
Сообщений: 120
13.11.2011, 14:33  [ТС] #3
Цитата Сообщение от silent_1991 Посмотреть сообщение
Напишите свой класс-исключение, унаследованный от std::exception, и ловите ссылку на его объект.
C++
1
2
3
4
5
6
7
#include <exception>
class MyExceptions:public std::exception
{
public:
    MyExceptions(void);
    ~MyExceptions(void);
};
подскажите пожалуйста: как добавить собственное исключение в этот клас?
0
fasked
Эксперт С++
4978 / 2557 / 241
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
13.11.2011, 14:34 #4
Цитата Сообщение от Scorpion93 Посмотреть сообщение
подскажите пожалуйста: как добавить собственное исключение в этот клас?
Этот класс и есть "исключение".
1
Scorpion93
2 / 2 / 3
Регистрация: 31.10.2010
Сообщений: 120
13.11.2011, 16:17  [ТС] #5
я понимаю, но как еще добавить исключения? скажем я делаю клас рациональная дробь и что бы в знаменателе не было 0. можно это без ifа и попыткой деления проверить?
0
fasked
Эксперт С++
4978 / 2557 / 241
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
13.11.2011, 16:45 #6
Scorpion93, таки непонятно, что именно вы хотите сделать? делаете класс рациональная дробь, добавляете свой класс исключения DivisionByZeroException, в методах класса рациональной дроби проверяете возможность возникновения ситуации деления на ноль и бросаете созданное исключение. В месте, откуда был вызван метод, отлавливаете это исключение и исправляетесь.
1
Scorpion93
2 / 2 / 3
Регистрация: 31.10.2010
Сообщений: 120
13.11.2011, 20:06  [ТС] #7
C++
1
2
3
4
5
6
7
8
9
void  MyRational::ConsoleInput()
{
    cout<<"Numerator: ";
    cin>>numerator;
    cout<<"Denumerator: ";
    cin>>denumerator;
    long temp=numerator/denumerator;
    
}
C++
1
2
3
4
5
6
7
8
try
    {
        a.ConsoleInput();
    }
    catch (exception& e)
    {
        cout << "Standard exception: " << e.what() << endl;
    }
программа не работает, выдает ошибку, но исключение не генерируется.. что за..?
0
silent_1991
Эксперт С++
5007 / 3067 / 270
Регистрация: 11.11.2009
Сообщений: 7,043
Завершенные тесты: 1
14.11.2011, 08:49 #8
Scorpion93, так а где вы кидаете исключение-то? В методе ConsoleInput, по крайней мере, вы его не выкидываете.
1
Scorpion93
2 / 2 / 3
Регистрация: 31.10.2010
Сообщений: 120
14.11.2011, 09:56  [ТС] #9
C++
1
  long temp=numerator/denumerator;
denumerator равно 0... тоесть должно возникать исключение... или нужен if?
0
silent_1991
Эксперт С++
5007 / 3067 / 270
Регистрация: 11.11.2009
Сообщений: 7,043
Завершенные тесты: 1
14.11.2011, 10:00 #10
Scorpion93, с чего бы оно должно возникать? Как программа узнает, что при делении на нуль нужно кидать пользовательское исключение? Это вам не дотнет, где за всем следит среда выполнения. Вы должны сами выбрасывать исключение в случае, если знаменатель равен нулю.
1
Bers
Заблокирован
14.11.2011, 10:05 #11
Исключения - неудачная практика, если их использовать не в исключительных ситуациях.
0
silent_1991
Эксперт С++
5007 / 3067 / 270
Регистрация: 11.11.2009
Сообщений: 7,043
Завершенные тесты: 1
14.11.2011, 14:15 #12
Bers, т.е. деление на нуль по-вашему - не исключительная ситуация?
0
Bers
Заблокирован
15.11.2011, 00:17 #13
Цитата Сообщение от silent_1991 Посмотреть сообщение
Bers, т.е. деление на нуль по-вашему - не исключительная ситуация?
Исключительная ситуация - это ситуация, спрогнозировать которую самостоятельно модуль не в состоянии.

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

Это нормальное положение вещей. Любой модуль должен быть готов к тому, что входные данные будут некорректными. И уметь корректно на это отреагировать. А не кидать в панике исключения, и не обрушивать весь процесс.
0
taras atavin
4204 / 1764 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
15.11.2011, 12:54 #14

Не по теме:

Цитата Сообщение от Scorpion93 Посмотреть сообщение
перезагнрузкой оператора
Правильно говорить "пергрузка", а перезагружают комп.

А теперь вопрос, относящийся к теме: как ты хочешь хранить свои числа: в паре действительная/мнимая часть, или в паре модуль/угол? В первом случае числа равны, если их части попарно равны, во втором - если части равны после приведения обоих углов к одному диапазону, не превышающим в размахе 360 градусов (http://www.cyberforum.ru/cgi-bin/latex.cgi?2*\pi радиан, 400 градов, 1000 тысячных и т.п.), например, к диапазону от минус ста восьмидесяти до плюс ста восьмидесяти градусов, а можно от ноля до тёхсот шестидесяти, но оба.
0
silent_1991
Эксперт С++
5007 / 3067 / 270
Регистрация: 11.11.2009
Сообщений: 7,043
Завершенные тесты: 1
15.11.2011, 13:35 #15
Цитата Сообщение от Bers Посмотреть сообщение
не кидать в панике исключения,
Цитата Сообщение от Bers Посмотреть сообщение
и не обрушивать весь процесс
Эти две фразы не являются эквивалентными. Для того и нужны исключения, чтобы не крашить программу в рантайме.
Каким образом вы восстановитесь после ошибки "деление на нуль"? Возможно, пользователь имел ввиду 1? Окей, давайте вместо нуля единичку подставим. Стоп. А вдруг он хотел 10?..
0
Bers
Заблокирован
15.11.2011, 13:55 #16
Цитата Сообщение от silent_1991 Посмотреть сообщение
Эти две фразы не являются эквивалентными.
Тем не менее, это - нарушение инварианта класса. Если он бросит исключение, а вызывающая сторона его не обработает, класс окажется виновником крэша.

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

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


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

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

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

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

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

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

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



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

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

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

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

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

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

Добавлено через 45 секунд
Цитата Сообщение от silent_1991 Посмотреть сообщение
Bers, чем деление на нуль отличается от выхода за границы массива?
Тем что деление на нуль - это деление на нуль.
А выход за пределы массива - это выход за пределы массива
1
taras atavin
4204 / 1764 / 211
Регистрация: 24.11.2009
Сообщений: 27,565
15.11.2011, 14:24 #20
Цитата Сообщение от Bers Посмотреть сообщение
Тем не менее, это - нарушение инварианта класса. Если он бросит исключение, а вызывающая сторона его не обработает, класс окажется виновником крэша.
Но если всё таки исключение необходимо, то придётся его бросить, иначе крах гарантированно будет до того, как кто то что то не обработает, а так хоть какая то надежда на продолжение работы. Но без нужды не кидать.
0
15.11.2011, 14:24
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.11.2011, 14:24

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

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

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


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

Или воспользуйтесь поиском по форуму:
20
Закрытая тема Создать тему
Опции темы

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