Конструктор преобразования не будет преобразовывать «2» в пользовательский тип в операторе + - PullRequest
2 голосов
/ 31 августа 2011

У меня есть класс с именем Fraction:

#ifndef FRACTION_H
#define FRACTION_H

#include <iostream>
using namespace std;

class Fraction
{
  // data
  int m_iNom;
  int m_iDenom;

  // operations
  int gcd (int i, int j);
  void reduce ();

public:

 Fraction (int nn=0, int dn=1); // 1 declaration = 3 constructors
 Fraction (const Fraction& fr); //C.Ctor
 ~Fraction (); //Dtor
 Fraction& operator = (const Fraction &fr); //assignment

 Fraction& operator ++ (); // prefix - ++a
  const Fraction operator ++ (int); // postfix - a++

  friend const Fraction operator + (const Fraction &f1, const Fraction &f2);
  friend const Fraction operator - (const Fraction &f1, const Fraction &f2);
  friend const Fraction operator * (const Fraction &f1, const Fraction &f2);
  friend const Fraction operator / (const Fraction &f1, const Fraction &f2);

 Fraction& operator += (const Fraction &f);

  operator double () { return double (m_iNom) / m_iDenom; } //casting operator

  friend istream& operator >> (istream &is, Fraction &f);
  friend ostream& operator << (ostream &os, const Fraction &f);
  const int& operator[] (int i) const;
  int& operator [] (int i);


};
#endif

со следующим файлом реализации:

#include "Fraction.h"
#include <iostream>
using namespace std;


Fraction::Fraction (int nn, int dd) :
   m_iNom (nn), m_iDenom (dd) {
  if (m_iDenom == 0)
  m_iDenom = 1;
 reduce ();
 cout<<"Ctor - Fraction: "<<m_iNom<<"/"<<m_iDenom<<endl;
}


Fraction::Fraction (const Fraction & fr){
 m_iNom=fr.m_iNom;
 m_iDenom=fr.m_iDenom;
 cout<<"C.Ctor - Fraction: "<<m_iNom<<"/"<<m_iDenom<<endl;
}

Fraction::~Fraction() {
 cout<<"del: "<<m_iNom<<"/"<<m_iDenom<<endl;
}


int Fraction::gcd (int i, int j) {
  if ((i == 0) || (j == 0))
   return i + j;
  while (i %= j) {
   int t = i;
  i = j;
  j = t;
 }
  return j;
}


void Fraction::reduce () {
  int g = gcd (m_iNom, m_iDenom);
 m_iNom /= g;
 m_iDenom /= g;
}


const Fraction operator + (const Fraction &f1, const Fraction &f2) {
  int nn = f1.m_iNom * f2.m_iDenom + f1.m_iDenom * f2.m_iNom;
  int dd = f1.m_iDenom * f2.m_iDenom;
  return Fraction (nn, dd);
}


const Fraction operator - (const Fraction &f1, const Fraction &f2) {
  int nn = f1.m_iNom * f2.m_iDenom - f1.m_iDenom * f2.m_iNom;
  int dd = f1.m_iDenom * f2.m_iDenom;
  return Fraction (nn, dd);
}


const Fraction operator * (const Fraction &f1, const Fraction &f2) {
  int nn = f1.m_iNom * f2.m_iNom;
  int dd = f1.m_iDenom * f2.m_iDenom;
  return Fraction (nn, dd);
}


const Fraction operator / (const Fraction &f1, const Fraction &f2) {
  int nn = f1.m_iNom * f2.m_iDenom;
  int dd = f1.m_iDenom * f2.m_iNom;
  return Fraction (nn, dd);
}


Fraction& Fraction::operator = (const Fraction &f)
{
 m_iNom = f.m_iNom;
 m_iDenom = f.m_iDenom;
 cout<<"OP = - Fraction: "<<m_iNom<<"/"<<m_iDenom<<endl;
  return *this;
}


Fraction& Fraction::operator += (const Fraction &f) {
 (*this) = (*this) + f;
  return *this;
}


Fraction& Fraction::operator ++ ()
{
 m_iNom += m_iDenom;
 reduce ();
  return *this;
}


const Fraction Fraction::operator ++ (int)
{
  int nn = m_iNom;
  int dd = m_iDenom;
 m_iNom += m_iDenom;
 reduce ();
  return Fraction (nn, dd);
}


istream& operator >> (istream &is, Fraction &frac)
{
  char divSign;
 is >> frac.m_iNom >> divSign >> frac.m_iDenom;
  if (frac.m_iDenom == 0)
  frac.m_iDenom = 1;
 frac.reduce ();
  return is;
}


ostream& operator << (ostream& os, const Fraction &frac)
{
  return os << frac.m_iNom << "/" << frac.m_iDenom;
}


int& Fraction::operator [] (int i){
 cout<<"reg []"<<endl;
  if (i==1)
   return m_iNom;
  return m_iDenom;
}


const int& Fraction::operator[] (int i) const{
 cout<<"const []"<<endl;
  if (i==1)
   return m_iNom;
  return m_iDenom;
}

и я пытаюсь выполнить действие Дробь f4 = f2 + 2; , но я получаю следующую ошибку компилятора:

..\main.cpp:13: error: ambiguous overload for 'operator+' in 'f2 + 2'
..\main.cpp:13: note: candidates are: operator+(double, int) <built-in>
..\Fraction.h:27: note:                 const Fraction operator+(const Fraction&, const Fraction&)

Но как это может быть, если у меня есть конструктор преобразования (обратите внимание на Ctor в файле .h со значениями по умолчанию) с одним аргументом, который предполагает преобразование «2» во дробную часть ... тогда что может быть проблема?

спасибо Ронен

Редактировать:

вот основной файл (если это поможет)

#include <iostream>
using namespace std;

#include "Fraction.h"

int main() {
    Fraction f1(1,2);
    Fraction f2(2);
    Fraction f3;

    Fraction f4=f2+2;  // problem's here 
    f2+f2;
    Fraction f5=f2-f1+f4;
    return 0;
}

Ответы [ 3 ]

3 голосов
/ 31 августа 2011

Компилятор не может решить, следует ли преобразовать f2 в double, затем добавить double и int или построить дробь из 2, а затем добавить две дроби.

Параметры:

  • Сделать оператор double () явным (C ++ 11)
  • Оператор перегрузки + принимать целые числа
2 голосов
/ 31 августа 2011

Проблема:

operator double ()

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

При оценке

Fraction f4=f2+2;

Компилятор имеет 2 варианта:

Первый выбор:

Компилятор может преобразовать f2 в double, используя предоставленную вами операторную функцию, а затем ее можно использовать для вызова встроенной операторной функции:

    operator+(double, int);

Второй выбор:

Компилятор может преобразовать 2 в объект Fraction, используя конструктор, а затем вызвать:

const Fraction operator+(const Fraction&, const Fraction&)

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

Решение:
Измените имя функции оператора double.

1 голос
/ 31 августа 2011

Компилятор действительно может сделать 2 варианта, когда вы напишите что-то вроде f2+2.

  • Сначала можно преобразовать 2 в дробь с помощью конструктора дроби, а затем использовать оператор + дроби.
  • Он может сначала преобразовать f2 в двойное число с помощью оператора двойной дроби, а затем просто добавить двойное и целое число

Чтобы решить проблему, вам придется либо явно указать конструктор, либо дать двойному оператору явное имя (например, toDouble).

...