Returning References

Discussion in 'Computer Science & Culture' started by S.Tarafdar, Jul 16, 2003.

Thread Status:
Not open for further replies.
  1. S.Tarafdar Registered Senior Member

    Messages:
    35
    I am trying to understand a class Rational,which has this public method:
    Rational & reduce(),which normalizes a fraction.This is what I wrote:
    Code:
     
    
    Rational &Rational::reduce(){ 
    int d=GCD(nom,den); //nom-numerator,den-
    nom=nom/d;              //denominator
    den=nom/d;
    return ?;
    }
     
    
    Now,my question is how I can return the object itself,as it has no parameter.Can it return more than one reference?

    Pls suggest me.
     
  2. Google AdSense Guest Advertisement



    to hide all adverts.
  3. AntonK Technomage Registered Senior Member

    Messages:
    1,083
    For any function that is a member of a class, it automatically has access to an element called "this" this always referes to the current object. Therefore all functions that are static do NOT have access to this object.

    My guess is that you'll want to:
    Code:
         return this;
    
    -AntonK
     
  4. Google AdSense Guest Advertisement



    to hide all adverts.
  5. S.Tarafdar Registered Senior Member

    Messages:
    35
    I have done so.The compiler shows this error:error C2440: 'return' : cannot convert from 'class Rational *const ' to 'class Rational &'
    A reference that is not to 'const' cannot be bound to a non-lvalue
     
  6. Google AdSense Guest Advertisement



    to hide all adverts.
  7. okinrus Registered Senior Member

    Messages:
    2,669
    You don't want to return a referance to the "this" object here. If you wanted to do that you could use *this. You really only need to do this for the assignment operation, operator+= etc. Usually it's best to keep all rational numbers relatively prime. In that case, you would just reduce in the constructor and any after any addition, subtraction operators. Anyways here is what some of the class will look like.

    Code:
    
    //...//
    
    class Rational {
           int n;
           int d;
    
          void reduce() { 
                 int g = gcd(n, d);
                 n /= g;
                 d /= g;
           }
    
    public:
           Rational(int numer, int denom) : n(numer), d(denom) { reduce(); }
    
           Rational& operator+=(const Rational& r2) {
                     Rational& r1 = *this;
                     
                     // add r1 and r2 and assign to r1
    
                     r1.reduce();
                     return r1;
           }
    
           // many more functions....
    };     
    
    // ... //
    
     
    Last edited: Jul 17, 2003
  8. S.Tarafdar Registered Senior Member

    Messages:
    35
    Thank you .Here are my complete codes:

    Code:
    
    #include<iostream>
    
    using namespace std;
    
    class Rational{
    int nom;
    int den;
    public:
    Rational();
    Rational(int a,int b);
    void print() const;
    double value() const;
    Rational& reduce();
    Rational& add(const Rational &r);
    };
    
    Rational::Rational(){
    nom=0;
    den=1;
    }
    
    Rational::Rational (int a,int b){
    nom=a;
    den=b;
    
    }
    
    int GCD(const int &n,const int &m){
    if(n%m==0)
      return m;
    else 
      return(m,n%m);
    }
    
    Rational &Rational::reduce(){ 
    int d=GCD(nom,den);
    nom=nom/d;
    den=nom/d;
    return (*this);
    }
    void Rational::print( void ) const{
    
       if ( den == 0 )
          cout << "\nDIVIDE BY ZERO ERROR!!!" << '\n';
       else if ( nom == 0 )
          cout << 0;
       else
          cout << nom << '/' << den;
    }
    
    
    double Rational::value() const{
    return (float) nom/(float) den;
    }
    
    Rational &Rational::add( const Rational &a )
    {
       Rational t;
    
       t.nom = a.nom * den + a.den * nom;
       t.den = a.den * den;
       t.reduce();
    
       return t;
    }
    
    int main(){
    Rational r1(3,8),r2(1,10);
    r1.print();
    r1.add(r2);
    r1.print();
    r1.add(Rational(1,40).print();
    r1.reduce().print();
    
    return 0;
    }
    
    But,unfortunately,it does not give the correct result. Furthermore,I want to change my add method so that it can use another function LCM(Least Common Multiple).

    Pls suggest.
     
  9. AntonK Technomage Registered Senior Member

    Messages:
    1,083
    Well, here's one problem. You call add, and it returns something, yet that returned value is lost because you dont assign it to anything.

    -AntonK
     
  10. S.Tarafdar Registered Senior Member

    Messages:
    35
    AntoK,would you please tell me in a bit more details so that I can understand?(I am a novice in programming!)
     
  11. AntonK Technomage Registered Senior Member

    Messages:
    1,083
    Well, you wrote a function:
    Code:
    Rational &Rational::add( const Rational &a )
    {
       Rational t;
    
       t.nom = a.nom * den + a.den * nom;
       t.den = a.den * den;
       t.reduce();
    
       return t;
    }
    
    Inside, you return a Rational. I think what you ACTUALLY want to do is this
    Code:
    void Rational::add( const Rational &a )
    {
       Rational t;
    
       t.nom = a.nom * den + a.den * nom;
       t.den = a.den * den;
       t.reduce();
    
       this = t;
    }
    
    If you DO want to use your original code and have the function return something you can do this
    Code:
    int main()
    {
       Rational r1(3,8),r2(1,10);
       r1.print();
       r1 = r1.add(r2);
       r1.print();
       r1 = r1.add(Rational(1,40).print();
       r1.reduce().print();
    
       return 0;
    }
    
    Basically, if you write a function that returns something, you have to assign that something to a variable.

    -AntonK
     
  12. okinrus Registered Senior Member

    Messages:
    2,669
    You should not assign "this" to point outside of the object. What is happening is that your add function is incorrect. You are returning a referance to a local object. Once the stack pops after the call to the function you do not have access to that memory. You can return by value. Also the way you have the add function it is not modifying the object but returning a new object. So you could have your add function look like this

    Code:
    Rational Rational::add( const Rational &a ) const
    {
       Rational t;
    
       t.nom = a.nom * den + a.den * nom;
       t.den = a.den * den;
       return t.reduce();
    }
    
    Your GCD function is also wrong.
    Code:
    int GCD(int n, int m)
    {
      if (m == 0) {
        return n;
      }
    
      return GCD(m, n % m);
    }
    
    In the reduce method is it is OK to return *this, because you assured that whoever is calling the function has allocated the object on the callee's stack frame. However you messed up. You want to do this

    Code:
    Rational &Rational::reduce()
    { 
      int d = GCD(nom,den);
      nom = nom/d;
      den = den/d;
      return (*this);
    }
    
    You probably want this
    Code:
    int main(){
        Rational r1(3,8),r2(1,10);
        r1.print();
        r1 = r1.add(r2);
        r1.print();
    
        // does not change r1
        r1.add(Rational(1,40)).print();
        r1.reduce().print();
    
        return 0;
    }
    
     
  13. S.Tarafdar Registered Senior Member

    Messages:
    35
    Thanks a lot.
    I have almost completed.Now,I want to test my program in a way that the main function accumulates 10 rational numbers a/b,where a is random value in [0,9] and b in [1,10].Now,it prints the resulting fraction for and after reducing as well as its decimal values.

    This is what I wrote:
    Code:
    #include<iostream>
    #include<cstdlib>
    #include<ctime>
    
    using namespace std;
    
    class Rational{
    int nom;
    int den;
    public:
    Rational();
    Rational(int a,int b);
    void print() const;
    double value() const;
    Rational& reduce();
    Rational& add(const Rational &r);
    };
    
    Rational::Rational(){
    nom=0;
    den=1;
    }
    
    Rational::Rational (int a,int b){
    nom=a;
    den=b;
    
    }
    
    int GCD( int n, int m){         //Is this method ok?
    if(m > n){
     int t = m;
     m = n;
     n = t;
    }
          if(!(n%m)){
                  return m; 
          }
          return GCD(m,n%m);
    
    }
    
    Rational &Rational::reduce(){ 
    int d=GCD(nom,den);
    nom=nom/d;
    den=den/d;
    return *this;
    }
    void Rational::print( void ) const{
    
      if ( den == 0 )
         cout << "\nDIVIDE BY ZERO ERROR!!!" << '\n';
      else if ( nom == 0 )
         cout << 0;
      else
         cout << nom << '/' << den;
    }
    
    
    double Rational::value() const{
    return (float) nom/(float) den;
    }
    
    int LCM(int n,int d){
    
    return ((n*d)/GCD(n,d));
    }
    
    Rational &Rational::add( const Rational &r )
    {
      int lcm=LCM(den,r.den);
      nom=nom*(lcm/den)+r.nom*(lcm/r.den);
      den=lcm;
      return *this;
    
    }
    
    int main(){
    	Rational r1(3,8),r2(1,10);
    	r1.print();
    	cout<<endl;
    	r1.add(r2);
    	r1.print();
    	cout<<endl;
    	r1.add(Rational(1,40)).print();
    	cout<<endl;
    	r1.reduce().print();
    	cout<<endl;
    	cout<<r1.value()<<endl;
    	cout<<"################################"<<endl;
    
    	//Test of the program
    	srand(time(NULL));
    
    	Rational a(0+rand()%10,2+rand()%10);
    	Rational *p;
    	p=&a;
    
    	for (int i=0;i<10;i++){
    		p->print();
    		cout<<endl;		
    		p++;
    	}
    	cout<<"***********";
    	for (int j=0;i<2;i++){
    		p->reduce().print();
    		
    		cout<<endl;		
    		p++;
    	}
    
    
    
    
    
    	return 0;
    }
    

    It is giving strange results.

    please suggestions once again.....
     
    Last edited: Jul 17, 2003
  14. AntonK Technomage Registered Senior Member

    Messages:
    1,083
    You really need to pay attention to what you're doing and trace it better in your head as you write it. Look at what you're doing. In your print function, you are already sending the information to cout, and then in your main, you try to return something from that function and put that to cout. The print function doesn't return anything, its void. I suggest scrapping this project and going for an intro to C++ book. Actually, learn C first. It's always better to learn C then learn C++.

    -AntonK
     
  15. S.Tarafdar Registered Senior Member

    Messages:
    35
    AntonK,infact all the codes are not visible there.And,I tried several times to paste this part there.I couldn't do it. In the main program after the second line,it shows faulty codes.I do not knw why.
    So,I do not deserve to be abased.Anyway,thank you for your help and suggestions.

    My main program was:
    (perhaps this is not as bad as you assumed)
    main(){
    Rational r1(3,8),r2(1,10);
    r1.print();
    cout<<endl;
    r1.add(r2);
    r1.print();
    cout<<endl;
    r1.add(Rational(1,40)).print();
    cout<<endl;
    r1.reduce().print();
    cout<<endl;
    cout<<r1.value()<<endl;
    cout<<"################################"<<endl;

    //Test of the program
    srand(time(NULL));

    Rational a(0+rand()%10,2+rand()%10);
    Rational *p;
    p=&a;

    for (int i=0;i<10;i++){
    p->print();
    cout<<endl;
    p++;
    }
    cout<<"***********";
    for (int j=0;i<2;i++){
    p->reduce().print();

    cout<<endl;
    p++;
    }

    return 0;
    }
     
Thread Status:
Not open for further replies.

Share This Page