argument type checkinng in Constructor



  • Thanks for your answer. Still not working. It looks like a simple problem but I try so many approaches already.



  • Try this:
    explicit Rational( int n, int d);

    This will forbid implicit typecasts resulting in a compile time error when you try to pass other types than int.



  • no it doesn't.

    It prevents automatic conversion which isn't possible anyway with two arguments.

    notkit:
    what doesn't work?
    Could you show an example?



  • Look interesting. I try it as you suggested but the constructor Rational(int n, int d) is still called when I call Rational(3.0, 4.0). The "3.0" and "4.0" are converted into integer and only warning are given.



  • try this:

    class Rational
    {
    public:
      Rational(int n, int d) { // your Code here }
    private:
      Rational(double n, double d); // no implmentation
    };
    
    int main()
    {
      Rational(2,3); // should work fine
      Rational(2.0,3.0); // should result in a compilation error
    }
    


  • Here you are. Class Rational is to represent rational number (e.g. 3/4) and normally a double should not be able to expressed as rational number. 😉

    // this is the header file
    class Rational
    {
    public:
    // Constructor
    Rational(int n = 0, int d = 1) // denomiator alway more than zero
    {
    if (d != 0) {
    m_num = n;
    m_den = d;
    if(m_den != 1)
    Normalize();
    }
    }

    // operators
    Rational &operator =(int i);

    operator double() { return (double)m_num/(double)m_den; }
    Rational operator +() { return Rational(m_num, m_den); }
    Rational operator -() { return Rational(-m_num, m_den); }

    Rational operator +(const Rational &src);
    double operator +(const double d);
    Rational operator -(const Rational &src);
    double operator -(const double d);
    Rational operator *(const Rational &src);
    double operator *(const double d);
    Rational operator /(const Rational &src);
    double operator /(const double d);

    // Print out the contents of the instance
    void Print(); // Implemented in the rational.cpp file

    // Access member functions
    int Numerator() { return m_num; }
    int Denominator() { return m_den; }

    private:
    // Private functions
    void Normalize(); // To be implemented in the rational.cpp file

    // Private data
    int m_num; // numerator
    int m_den; // denominator
    };

    //
    int main()
    {
    a = 1.0; // Should not compile
    a = Rational(3.0, 3.0); // Should not compile

    return 0;
    }



  • This is the implementation for Rational class.

    #include <iostream.h>
    #include "rational.h"

    void Rational::Normalize()
    {
    if (m_den<0) {
    m_num = -m_num;
    m_den = -m_den;
    } else {
    m_num = m_num;
    m_den = m_den;
    }

    if (m_num == 0) {
    return;
    }

    // Euclid's algorithm...
    int a, b, r;

    if (m_num > 0 && m_num > m_den) {
    a = m_num;
    b = m_den;
    } else if (m_num > 0){
    a = m_den;
    b = m_num;
    } else if (-m_num > m_den) {
    a = -m_num;
    b = m_den;
    } else {
    a = m_den;
    b = -m_num;
    }

    r = 1;
    while (r > 0)
    {
    r = a % b;
    a = b;
    b = r;
    }

    // record the normalized value to m_num and m_den
    m_num = m_num/a;
    m_den = m_den/a;

    return;

    }

    void Rational::Print()
    {
    cout << "(" << m_num << "/" << m_den << ")";
    }

    Rational &Rational::operator =(int i)
    {
    m_num = i;
    m_den = 0;
    return *this;
    }

    Rational Rational::operator +(const Rational &src)
    {
    return( Rational( m_num*src.m_den + src.m_num*m_den, m_den*src.m_den ) );
    }

    double Rational::operator +(const double d)
    {
    return( double(m_num)/double(m_den) + d );
    }

    Rational Rational::operator -(const Rational &src)
    {
    return( Rational( m_num*src.m_den - src.m_num*m_den, m_den*src.m_den ) );
    }

    double Rational::operator -(const double d)
    {
    return( double(m_num)/double(m_den) - d );
    }

    Rational Rational::operator *(const Rational &src)
    {
    return( Rational( m_num*src.m_num, m_den*src.m_den ) );
    }

    double Rational::operator *(const double d)
    {
    return( double(m_num)/double(m_den) * d );
    }

    Rational Rational::operator /(const Rational &src)
    {
    return( Rational( m_num*src.m_den, m_den*src.m_num ) );
    }

    double Rational::operator /(const double d)
    {
    return( double(m_num)/double(m_den) / d );
    }



  • Beats me where you left Jester's suggestion. Already disposed of it? 😃
    You should honestly give it a try; public for linker-, private for compiler-error.

    NB:

    Rational &Rational::operator =(int i)
    {
      m_num = i;
      // m_den = 0; // this ain't exactly what you want, is it? how 'bout that:
      m_den = 1;
      return *this;
    }
    
    // moreover,
    if (m_den<0) {
      m_num = -m_num;
      m_den = -m_den;
    }
    // else branches aren't mandatory  ;) 
    /*
      else {
      m_num = m_num;
      m_den = m_den;
    } 
    */
    


  • to Jester,

    cool. The Rational(3.0, 4.0) does not compile now. But the

    Rational a;
    a = 3.0; // Ratinal = double should not compile

    still compiles. And this should not because double should not be expressed as Rational numbers.



  • use the same technique for operator=



  • Oh finally. Problem solved. I was like trying to solve this easy-looking problems for days. Danke Sehr! Danke schon! Danke Danke! Ho! 😉


Anmelden zum Antworten