Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Класс для работы с дробями, Перегрузка операторов 
:(
    Опции темы
Superklug
Дата 23.2.2010, 20:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 227
Регистрация: 16.6.2006

Репутация: нет
Всего: нет



Доброго времени суток!
Пишу класс для работы с дробями.. Хотелось бы добиться полной совместимости с int. 
Код

class drob
{
private:
    int ch, zn;
    int NOD( int a, int b);
    void sokr();

public:
    drob( int tch = 0, int tzn = 1 );

    int znam();
    void znam( int tzn);

    int chisl();
    void chisl( int tch);

    friend bool operator>(drob d1, drob d2);
    friend bool operator<(drob d1, drob d2);
    friend bool operator>=(drob d1, drob d2);
    friend bool operator<=(drob d1, drob d2);
    friend bool operator==(drob d1, drob d2);
    friend bool operator!=(drob d1, drob d2);

    friend drob operator+(drob d1, drob d2);
    friend drob operator-(drob d1, drob d2);
    friend drob operator*(drob d1, drob d2);
    friend drob operator/(drob d1, drob d2);
    
    drob operator+=(drob d);
    drob operator-=(drob d);
    drob operator*=(drob d);
    drob operator/=(drob d);

    operator int();
}


В случае если пытаюсь написать что-нибудь вроде:
Код

drob a(7,3);
int b = 5;
int c = b + a;

Возникает ошибка: error C2666: 'operator +' : 2 overloads have similar conversions
Как избежать этого?


PM MAIL   Вверх
Ockonal
Дата 23.2.2010, 20:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Smile
*


Профиль
Группа: Участник
Сообщений: 219
Регистрация: 9.7.2007
Где: Ukraine::Nikolaev ;

Репутация: нет
Всего: 3



Да, я тут писал класс для работы с дробями: http://wincode.org.ua/?p=245
----
А по вопросу конкретно: http://kbalertz.com/106392/C2666-Error-Gen...d-Operator.aspx

Это сообщение отредактировал(а) Ockonal - 23.2.2010, 20:45
--------------------
Ум заключается не только в знании, но и в умении прилагать знание на деле.Самое лучшее из всех доказательств есть опыт.Каждому человеку свойственно ошибаться, но никому, кроме глупца, несвойственно упорствовать в ошибке.
PM MAIL WWW ICQ Skype GTalk Jabber MSN   Вверх
Superklug
Дата 23.2.2010, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 227
Регистрация: 16.6.2006

Репутация: нет
Всего: нет



Ockonal, ваш класс не совсем то, что мне нужно... 
Мне бы хотелось добиться такого, что работать с моим классом вместе с int будет так же просто как и double вместе с int...

На сколько я понимаю ошибка заключается в том, что компилятор не может выбрать между int+drob и int+int..
Можно конечно всегда явно указывать (int), но как-то же можно реализовать иначе?

Это сообщение отредактировал(а) Superklug - 23.2.2010, 21:17
PM MAIL   Вверх
Леопольд
Дата 24.2.2010, 09:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 3
Всего: 13



Цитата(Superklug @  23.2.2010,  20:30 Найти цитируемый пост)
Возникает ошибка: error C2666: 'operator +' : 2 overloads have similar conversions

Добавь 
Код

template<typename T>
drob operator+(T d1, drob d2){
    return drob(d1) + d2;
}


Добавлено через 9 минут и 9 секунд
Цитата(Superklug @  23.2.2010,  21:16 Найти цитируемый пост)
компилятор не может выбрать между int+drob и int+int

Так и есть. Компилятор перед выбором.

operator+(drob(b), a)
    или
b + a.operator int()

Добавлено через 11 минут и 25 секунд
Оба выражения включают в себя по одному пользовательскому преобразованию и поэтому равнозначны. Функция, где не будет таких неявных преобразований будет препочтительнее тем двум.

Это сообщение отредактировал(а) Леопольд - 24.2.2010, 09:18


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
bsa
Дата 24.2.2010, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Superklug, operator int() лишний. От него лучше избавиться, так как из-за него будет ОЧЕНЬ много проблем.

Добавлено через 1 минуту и 11 секунд
Я бы вместо drob operator +=(drob x) писал бы drob& operator +=(const drob &x) - меньше лишних операций копирования.
PM   Вверх
Superklug
Дата 24.2.2010, 15:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 227
Регистрация: 16.6.2006

Репутация: нет
Всего: нет



Леопольд, спасибо! Сейчас попробую разобраться...


bsa, я б с радостью избавился... Но не умею по другому. Как без него сделать работоспособным след код:
Код

drob d(5,2);
int n = d;


А по поводу ссылок знаю.. Просто на форуме заморачиваться не стал smile
PM MAIL   Вверх
Superklug
Дата 24.2.2010, 15:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 227
Регистрация: 16.6.2006

Репутация: нет
Всего: нет



Леопольд, выходит надо добавлять по два шаблона для каждого оператора? Например:
Код

template<typename T> drob operator+(T d1, drob d2);
template<typename T> drob operator+(drob d1, T d2);


И еще, если оставить ф-ю drob operator+(drob d1, drob d2), то та ошибка возникает снова. Можно операции реализовывать непосредственно в шаблонных функциях..

Я правильно мыслю? Или усложнил все)
PM MAIL   Вверх
bsa
Дата 24.2.2010, 16:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(Superklug @  24.2.2010,  15:37 Найти цитируемый пост)
Как без него сделать работоспособным след код
А не надо его делать работоспособным. Так как эта функциональность провоцирует ошибки.
Более того, в библиотеке boost во всех типах, которые можно привести к bool (например, умные указатели - проверка на NULL), делают это через оператор преобразования к указателю на метод этого типа. И делают это специально, чтобы не дай бог случилось, что кто-то случайно ошибся и компилятор это молча проглотил...


Цитата(Superklug @  24.2.2010,  15:58 Найти цитируемый пост)
Я правильно мыслю? Или усложнил все) 
Я тебе уже написал про оператор преобразования. Все эти и будущие проблемы именно в нем.

PM   Вверх
Леопольд
Дата 24.2.2010, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 3
Всего: 13



Цитата(Superklug @  24.2.2010,  15:58 Найти цитируемый пост)
Леопольд, выходит надо добавлять по два шаблона для каждого оператора?

Два не надо, в случае с a + b будет вызов drob operator+ (a, drob(b))
Я лишь показал как можно обойти проблему. Однако operator int() ещё может тебе напакостить. Можно где-нибудь легко получить двойное пользовательское преобразование, к примеру:
Код
#include <iostream>

struct Test1{
    operator char() {
        std::cout<<"Test1"<<std::endl;
        return 0;
    }
};
//struct Test2: public Test1{ а так будет работать, только не забудь закомментировать строку ниже.
struct Test2{
    Test2(){}
    operator Test1() {
        std::cout<<"Test2"<<std::endl;
        return Test1();
    }
};
void foo(char){}

int main()
{
    foo(Test2());
    return 0;
}


Но лучше просто убарть operator int(), как уже заметил bsa:

Код

#include <iostream>

class drob
{
private:
    int ch, zn;
    static int abs(int a){
        return a>0 ? a : -a;
    }
    static int NOD(int a, int b){
        a = abs(a);
        b = abs(b);
        while (a != b){
            if (a > b)
                a -= b;
            else
                b -= a;
        }
        return a;
    }

public:
    drob(int tch = 0, int tzn = 1 ):ch(tch/NOD(tch, tzn)), zn(tzn/NOD(tch, tzn)) {}

    int znam() const{
        return zn;
    }
    void znam(int tzn){
        zn = tzn;
    }

    int chisl() const{
        return ch;
    }
    void chisl(int tch){
        ch = tch;
    }


    friend drob operator+(const drob& d1, const drob& d2);
};

drob operator+(const drob& d1, const drob& d2){
    int ch = d1.ch * d2.zn + d2.ch * d1.zn;
    int zn = d1.zn * d2.zn;
    return drob(ch, zn);
}

std::ostream& operator<< (std::ostream& out, const drob& d){
    out<<d.chisl()<<'/'<<d.znam();
    return out;
}

int main()
{
    drob a(10,12);
    std::cout<<a<<std::endl;
    drob b = -2 + a; // здесь сработает конструктор - drob(2)
    std::cout<<b<<std::endl;
    return 0;
}


Это сообщение отредактировал(а) Леопольд - 25.2.2010, 09:53


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

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


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0933 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.