Russian Qt Forum

Программирование => С/C++ => Тема начата: Даниил от Октябрь 09, 2011, 17:20



Название: Перегрузка оператора *
Отправлено: Даниил от Октябрь 09, 2011, 17:20
Здравствуйте.

Пишу класс, для работы с простыми дробями. Застрял на перегрузке операторов.
Стандартная ситуация: необходимо выполнять математический оператор и возвращать полученное значение.
Класс:
Код
C++ (Qt)
class TFrac
{
public:
   TFrac();
   TFrac(int a, int b);
   TFrac(QString drob);
 
   void operator =      (TFrac &other);
   TFrac& operator *      (TFrac &other);
 
private:
   int chislitel;
   int znamenatel;
};
 
Реализация:
Код
C++ (Qt)
void TFrac::operator =(TFrac &other)
{
   this->chislitel = other.chislitel;
   this->znamenatel = other.znamenatel;
}
TFrac& TFrac::operator *(TFrac const &other)
{
       this->chislitel *= this->chislitel;
       this->znamenatel *= this->znamenatel;
       return *this;
}
 

Main:
Код
C++ (Qt)
...
TFrac first(1,3);
TFrac second(2,3);
TFrac third;
third = first * second;
...
 
Внимание, вопрос: как осуществить умножение, не изменяя первый операнд?


Название: Re: Перегрузка оператора *
Отправлено: Nimbus от Октябрь 09, 2011, 17:29
>TFrac& operator *      (TFrac &other);
>TFrac& TFrac::operator *(TFrac const &other)
А оно вообще "конпелируется"?  :)

Надо так:
Код
C++ (Qt)
//Declaration
TFrac& operator *      (const TFrac &other) const;
//Implementation
TFrac& TFrac::operator *(const TFrac  &other) const {
   return TFrac(chislitel * other.chislitel,
       znamenatel * other.znamenatel);
}
 
Если конечно твой конструктор TFrac(int a, int b) инициализирует числитель и знаменатель ;)


Название: Re: Перегрузка оператора *
Отправлено: Даниил от Октябрь 09, 2011, 17:36
>TFrac& operator *      (TFrac &other);
>TFrac& TFrac::operator *(TFrac const &other)
А оно вообще "конпелируется"?  :)
Если конечно твой конструктор TFrac(int a, int b) инициализирует числитель и знаменатель ;)

Оно компилириуется, а вот так как ты указал - нет.
Код:
TFrac.cpp:194: ошибка: invalid initialization of non-const reference of type 'TFrac&' from a temporary of type 'TFrac'


Название: Re: Перегрузка оператора *
Отправлено: Nimbus от Октябрь 09, 2011, 17:41
Оно компилириуется, а вот так как ты указал - нет.
Код:
TFrac.cpp:194: ошибка: invalid initialization of non-const reference of type 'TFrac&' from a temporary of type 'TFrac'
Пардон. Убери из объявления возвращаемого значения ссылку (&), т. е.:
TFrac operator *      (const TFrac &other) const;
и
TFrac TFrac::operator *(const TFrac  &other) const


Название: Re: Перегрузка оператора *
Отправлено: kambala от Октябрь 09, 2011, 17:43
потому что в коде JC присутствует & - ссылка на временную переменную, что и сказано в ошибке. убирание амперсанда всё решит.

оператор присваивания тоже весело объявлен у тебя :)
Код
C++ (Qt)
TFrac &TFrac::operator =(const TFrac &other)
{
   if (this != &other)
   {
       this->chislitel = other.chislitel;
       this->znamenatel = other.znamenatel;
   }
   return *this;
}


Название: Re: Перегрузка оператора *
Отправлено: Даниил от Октябрь 09, 2011, 17:45
потому что в коде JC присутствует & - ссылка на временную переменную, что и сказано в ошибке. убирание амперсанда всё решит.

оператор присваивания тоже весело объявлен у тебя :)
Код
C++ (Qt)
TFrac &TFrac::operator =(const TFrac &other)
{
   if (this != &other)
   {
       this->chislitel = other.chislitel;
       this->znamenatel = other.znamenatel;
   }
   return *this;
}

Лять ... из-за тебя еще и оператор != перегружать  ;D
Да, кстати такой код работает ТОЛЬКО в таком виде:
Код
C++ (Qt)
...
TFrac third = first * second;
...
 
А так, как у меня написано:
Код
C++ (Qt)
...
TFrac fhird();
third = first * second;
...
 
Вываливается ошибка:
Код:
main.cpp:13: ошибка: no match for 'operator=' in 'third = first.TFrac::operator*(((const TFrac&)((const TFrac*)(& second))))'


Название: Re: Перегрузка оператора *
Отправлено: kambala от Октябрь 09, 2011, 17:49
там сравнение указателей ;)


Название: Re: Перегрузка оператора *
Отправлено: Nimbus от Октябрь 09, 2011, 17:56

Код
C++ (Qt)
...
TFrac third = first * second;
...
 

Логично, потому что это дефолтный конструктор копирования вызывается.


Название: Re: Перегрузка оператора *
Отправлено: Даниил от Октябрь 09, 2011, 17:59
Логично, потому что это дефолтный конструктор копирования вызывается.
Спасибо, за справку.
А как недефолтный сделать?  ;)


Название: Re: Перегрузка оператора *
Отправлено: Nimbus от Октябрь 09, 2011, 18:02
А как недефолтный сделать?  ;)
Перегрузи, если ещё не перегружен. И реализуй его так же как operator=. Только там не нужно проверять адрес и возвращать значение.
И вообще, это незачем, если нет нужды в глубоком копировании.
Проблема в чём-то другом. Почему он указал ((const TFrac&)((const TFrac*)(& second))), в частности звёздочку - вот это интересно. И почему там second, а не other? ;)


Название: Re: Перегрузка оператора *
Отправлено: Igors от Октябрь 09, 2011, 19:21
Возвращение ссылки лучше оставить для оператора *= а умножение (и др. арифметику) сделать так 
Код
C++ (Qt)
class TFrac
{
public:
..  
friend TFrac operator * ( const TFrac & f1, const TFrac & f2 )  { return TFrac(f1.a * f2.a, f1.b * f2.b); }
...
int a, b;
};

Также
Код
C++ (Qt)
   int chislitel;
   int znamenatel;
 
Обычно члены таких классов float или double, ну да ладно. А вот длина имен совершенно неподходящая, при интенсивном обращении Вы быстро устанете их писать. В данном конкретном случае короткие имена лучше, из одной буквы - еще лучше. Также нечего стесняться сделать все public - нет правил без исключений


Название: Re: Перегрузка оператора *
Отправлено: Даниил от Октябрь 09, 2011, 19:52
Собственно проблему не решает, по прежнему ругается на присваивание:
Код:
main.cpp:13: ошибка: no match for 'operator=' in 'third = operator*(((const TFrac&)((const TFrac*)(& first))), ((const TFrac&)((const TFrac*)(& other))))'


Название: Re: Перегрузка оператора *
Отправлено: Nimbus от Октябрь 10, 2011, 04:18
Собственно проблему не решает, по прежнему ругается на присваивание:
Код:
main.cpp:13: ошибка: no match for 'operator=' in 'third = operator*(((const TFrac&)((const TFrac*)(& first))), ((const TFrac&)((const TFrac*)(& other))))'
Выложи уже свой код полностью


Название: Re: Перегрузка оператора *
Отправлено: Даниил от Октябрь 10, 2011, 06:35
Выложи уже свой код полностью
Не думаю, что вы там что-то новое увидите.


Название: Re: Перегрузка оператора *
Отправлено: Nimbus от Октябрь 10, 2011, 07:04
Не думаю, что вы там что-то новое увидите.
То-то и оно, что проблема в operator=, потому что ты оставил свой вариант, а не сделал как посоветовал kambala тут (http://www.prog.org.ru/index.php?topic=19665.msg133015#msg133015)
Он должен возвращать TFrac&, а у тебя он void возвращает ;)


Название: Re: Перегрузка оператора *
Отправлено: Даниил от Октябрь 10, 2011, 07:08
Он должен возвращать TFrac&, а у тебя он void возвращает ;)
Один хрен. Ошибка та же.

Вай, заработало) Недоглядел чуток. Спасибо всем.


Название: Re: Перегрузка оператора *
Отправлено: Даниил от Октябрь 10, 2011, 07:48
Вылез другой вопрос, не совсем к теме, но все же.
Как впилить описание friend метода, вне класса?
Код
C++ (Qt)
class TFrac
{
...
friend TFrac operator * ( const TFrac & f1, const TFrac & f2 )  { return TFrac(f1.a * f2.a, f1.b * f2.b); }
...
}
 
Как указал Igors, работает вполне себе ничего.
А вот если я описание метода выношу в другой файл. (Нужно мне так!)
Код
C++ (Qt)
TFrac TFrac::operator *(const TFrac &f1, const TFrac &f2)
{
       return TFrac(f1.chislitel * f2.chislitel, f1.znamenatel * f2.znamenatel);
}
 
Вылазиет ошибка:
Код:
TFrac.cpp:154: ошибка: 'TFrac TFrac::operator*(const TFrac&, const TFrac&)' must take either zero or one argument


Название: Re: Перегрузка оператора *
Отправлено: Nimbus от Октябрь 10, 2011, 08:26
Если оператор friend, то он не является членом класса.
Описание в .h(.hpp)
Код
C++ (Qt)
class TFrac {
...
friend TFrac operator * ( const TFrac & f1, const TFrac & f2 );
...
}
 
Реализация в .cpp
Код
C++ (Qt)
TFrac operator * ( const TFrac & f1, const TFrac & f2 ); {
return TFrac(f1.chislitel * f2.chislitel, f1.znamenatel * f2.znamenatel);
}
 


Название: Re: Перегрузка оператора *
Отправлено: Даниил от Октябрь 10, 2011, 08:38
Спасибо. Больше вопросов нет.