Thread: Problem with friend function

  1. #1
    Registered User
    Join Date
    Nov 2011
    Posts
    11

    Problem with friend function

    dear everybody ..

    I'm trying to understand operator overloading with my class (Complex) that handles complex numbers .. I'd like to allow such an operation

    Code:
    Complex c1(2,-3);         //c1=2-3i
    Complex c2(0,0);          //c2=0;
    c2=3+c1;                    //c2 should equal 5-3i
    c1 will not call the operator overloading function, instead, the compiler will call it with two parameters: 4 and c1 .. so the overloading function should be defined as standalone function outside Complex class and should look like this:

    Code:
    Complex operator +(float r, Complex c)
    {
        return Complex(r+c.getReal(),c.getImag());
    }


    My problem is:
    When the overloading function is defined as above, it doesn't work probably, but if it has been defined as a friend function inside the class, it's perfect.

    I'm confused because even I don't use friend function, I'm still using getters to access private members like real and imag, so my understanding guides me that there is no need for friend function !!

    Can anybody help ?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by afesheir
    When the overloading function is defined as above, it doesn't work probably, but if it has been defined as a friend function inside the class, it's perfect.
    That does not make sense unless getReal or getImag, or the constructor, is not public.

    Anyway, a typical approach is to define a member operator+=, then define operator+ in terms of operator+=. For example:
    Code:
    Complex& Complex::operator+=(float r)
    {
        // ...
        return *this;
    }
    
    Complex operator+(float r, Complex c)
    {
        return c += r;
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Define what you mean by "it doesn't work probably".

    Are you getting a compilation error? If so, what are the error messages? Does the code compile and link, but give unexpected results? If so, what are the results you expect, and how are the results you get different?

    How about providing a small but complete example of code that exhibits your problem?

    Currently, the information you have given is insufficient to allow anyone else to recreate your problem, let alone to properly understand it. So you cannot expect useful advice.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  4. #4
    Registered User
    Join Date
    Nov 2011
    Posts
    11
    laserlight .. that's fine, but what's wrong with my code ? why does (friend) keyword cause my program to operate or not to operate ??

    grumpy .. it doesn't work meaning that I get garbage output, no compile error

    here is my full code:

    Complex Class:
    Code:
    class Complex
    {
        private:
            float real, imag;
        public:
    
    
            Complex()
            {
                setAll();
                cout<<"Cn"<<endl;
            }
    
    
    //        Complex (Complex &c)
    //        {
    //            cout<<"CC"<<endl;
    //        }
            //friend Complex operator +(float r,Complex c);
            Complex(float i)
            {
                setImag(i);
                cout<<"Ci"<<endl;
            };
    
    
            Complex(float r,float i)
            {
                this->setAll(r,i);
                cout<<"Cri"<<endl;
            }
    
    
            ~Complex()
            {
                cout<<"D"<<endl;
            }
    
    
            void setReal(float r)
            {
                real=r;
            }
            void setImag(float i)
            {
                imag=i;
            }
            float getReal()
            {
                return real;
            }
            float getImag()
            {
                return imag;
            }
            void setAll()
            {
                this->real=this->imag=0;
            }
    
    
            void setAll(float r, float i)
            {
                this->real=r;
                this->imag=i;
            }
    
    
            Complex operator +(Complex c)
            {
                Complex t;
                t.setReal(real+c.getReal());
                t.setImag(imag+c.getImag());
                return t;
            }
    
    
            Complex operator +(float r)
            {
                return Complex(r+real,imag);
            }
    
    
            Complex operator -(float r)
            {
                return Complex(r-real,imag);
            }
    
    
            operator float()
            {
                return real;
            }
    
    
            Complex operator -(Complex c)
            {
                Complex t;
                t.setReal(real-c.getReal());
                t.setImag(imag-c.getImag());
                return t;
            }
    
    
            Complex operator =(Complex c)
            {
                real=c.getReal();
                imag = c.getImag();
                return *this;
            }
    
    
            int operator ==(Complex c)
            {
                return ((real==c.getReal())&&(imag==c.getImag()));
            }
    
    
            void operator +=(float v)
            {
                real+=v;
                imag+=v;
            }
    
    
            void operator -=(float v)
            {
                real-=v;
                imag-=v;
            }
    
    
           /* Complex operator *(Complex c)
            {
                return Complex(real*c.getReal - imag*c.getImag(),real*c.getImag() + imag*c.getReal());
            } */
    
    
            void printme()
            {
                printf("%f+ i(%f)\n",real,imag);
            }
    
    
            //friend Complex operator +(float r,Complex c);
    };
    and the main.cpp file:

    Code:
    int main()
    {
        Complex c1(-2,-7);
        Complex c2(-1,-7);
    
    
    
    
        c1=2.4+c1;
        c1.printme();
        return 0;
    }

    Thanks for interest and sorry for late reply

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by afesheir
    that's fine, but what's wrong with my code ? why does (friend) keyword cause my program to operate or not to operate ??
    I observe:
    Code:
    Complex(float i)
    {
        setImag(i);
        cout<<"Ci"<<endl;
    };
    This is bad because you failed to set the real part, and in fact this is probably the cause of the "garbage" that you saw printed. Furthermore, you did not declare the constructor as explicit, allowing implicit conversions from float to Complex.

    Now observe:
    Code:
    operator float()
    {
        return real;
    }
    So, converting from float to Complex creates a Complex object with only the imaginary part set, then converting from Complex to float creates a float that has a value of the real, not imaginary part. This is inconsistent. Oh, and again, you are allowing an implicit conversion from float to Complex. Allowing an implicit conversion in one direction can be useful despite the potential pitfalls; allowing implicit conversions in both directions is asking for trouble.

    My suggestions are:
    • Rewrite that constructor to set the real part to the argument, and set the imaginary part to 0.
    • Declare that constructor as explicit.
    • Replace operator float() with a named function, or declare it explicit (your compiler might not support this latter option).
    • Implement non-member non-friend operator+ in terms of operator+=.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Nov 2011
    Posts
    11
    laserlight .. that's fine, but what's wrong with my code ? why does (friend) keyword cause my program to operate or not to operate ??

    grumpy .. it doesn't work meaning that I get garbage output, no compile error

    here is my full code:

    Complex Class:
    Code:
    class Complex
    {
        private:
            float real, imag;
        public:
    
    
            Complex()
            {
                setAll();
                cout<<"Cn"<<endl;
            }
    
    
    //        Complex (Complex &c)
    //        {
    //            cout<<"CC"<<endl;
    //        }
            //friend Complex operator +(float r,Complex c);
            Complex(float i)
            {
                setImag(i);
                cout<<"Ci"<<endl;
            };
    
    
            Complex(float r,float i)
            {
                this->setAll(r,i);
                cout<<"Cri"<<endl;
            }
    
    
            ~Complex()
            {
                cout<<"D"<<endl;
            }
    
    
            void setReal(float r)
            {
                real=r;
            }
            void setImag(float i)
            {
                imag=i;
            }
            float getReal()
            {
                return real;
            }
            float getImag()
            {
                return imag;
            }
            void setAll()
            {
                this->real=this->imag=0;
            }
    
    
            void setAll(float r, float i)
            {
                this->real=r;
                this->imag=i;
            }
    
    
            Complex operator +(Complex c)
            {
                Complex t;
                t.setReal(real+c.getReal());
                t.setImag(imag+c.getImag());
                return t;
            }
    
    
            Complex operator +(float r)
            {
                return Complex(r+real,imag);
            }
    
    
            Complex operator -(float r)
            {
                return Complex(r-real,imag);
            }
    
    
            operator float()
            {
                return real;
            }
    
    
            Complex operator -(Complex c)
            {
                Complex t;
                t.setReal(real-c.getReal());
                t.setImag(imag-c.getImag());
                return t;
            }
    
    
            Complex operator =(Complex c)
            {
                real=c.getReal();
                imag = c.getImag();
                return *this;
            }
    
    
            int operator ==(Complex c)
            {
                return ((real==c.getReal())&&(imag==c.getImag()));
            }
    
    
            void operator +=(float v)
            {
                real+=v;
                imag+=v;
            }
    
    
            void operator -=(float v)
            {
                real-=v;
                imag-=v;
            }
    
    
           /* Complex operator *(Complex c)
            {
                return Complex(real*c.getReal - imag*c.getImag(),real*c.getImag() + imag*c.getReal());
            } */
    
    
            void printme()
            {
                printf("%f+ i(%f)\n",real,imag);
            }
    
    
            //friend Complex operator +(float r,Complex c);
    };
    and the main.cpp file:

    Code:
    int main()
    {
        Complex c1(-2,-7);
        Complex c2(-1,-7);
    
    
    
    
        c1=2.4+c1;
        c1.printme();
        return 0;
    }

    Thanks for interest and sorry for late reply

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Eh, afesheir, you seem to have re-posted your previous post.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    You've defined an operator + that takes a float as its first argument, but I've yet to see you give it a float at the first argument.
    I've seen the first argument being an int and later a double.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  9. #9
    Registered User
    Join Date
    Nov 2011
    Posts
    11
    yeap I've posted twice by mistake
    float is more precise as I wrote
    Code:
    c2=c1+2.4;
    2.4 seems to be float rather than integer .. even if I add integer value, it will be automatically up-casted to float ..

  10. #10
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    2.4 as a literal value is of type double, not float.

    And, yes, when adding an integer to a float (or a double) the integer will be converted to float (or double). That has been a feature of C for 40 years or more, so it is only natural you missed it .....
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. "Problem with friend function"
    By Shidlingayya in forum C++ Programming
    Replies: 2
    Last Post: 10-25-2011, 08:30 AM
  2. Problem in Matrix Multiplication (Using friend function)
    By wantsree in forum C++ Programming
    Replies: 3
    Last Post: 02-09-2011, 08:03 AM
  3. Visual C++ friend function problem
    By cs378 in forum C++ Programming
    Replies: 3
    Last Post: 03-23-2004, 09:05 PM
  4. friend function and friend classes...usage question??
    By actionbasti in forum C++ Programming
    Replies: 2
    Last Post: 10-30-2003, 10:53 PM