views:

207

answers:

6

Hello,

If I have the following files, I get this error (c2593 in VC9). If I un-comment the prototype in main.cpp, the error disappears. I need to maintain the same functionality while keeping the class out of main.cpp. How can I do that?

Thanks.

main.cpp:

#include "number.h"

//const Number operator + (const Number & lhs, const Number & rhs);

int main(void)
{
    Number n1(2);       // n1 = 2
    Number n2(9,3);     // n2 = 3
    Number n3 = n1+n2;  // n3 = 5
}

number.h:

struct Number
{
    int num;
    Number(int n=0,int d=1) {num = n/d;}
    operator int() {return num;}
    operator double() {return num*1.0;}
};

number.cpp:

#include "Number.h"

const Number operator + (const Number & lhs, const Number & rhs)
{
Number tmp;
tmp.num = lhs.num + rhs.num;
return tmp;
}
+1  A: 

That commented line should go in number.h

EDIT: in number.h but as a free function.

Chris H
number.h doesn't have any commented line.
thephpdeveloper
I mean, take the commented line from main.cpp and put it in number.h
Chris H
+4  A: 

Try putting the prototype in the Number header file:

number.h:

struct Number
{
    int num;
    Number(int n=0,int d=1) {num = n/d;}
    operator int() {return num;}
    operator double() {return num*1.0;}
};

const Number operator + (const Number & lhs, const Number & rhs);

number.cpp:

#include "Number.h"

const Number operator + (const Number & lhs, const Number & rhs)
{
Number tmp;
tmp.num = lhs.num + rhs.num;
return tmp;
}

main.cpp:

#include "number.h"

int main(void)
{
    Number n1(2);       // n1 = 2
    Number n2(9,3);     // n2 = 3
    Number n3 = n1+n2;  // n3 = 5
}
Bill
+1, of course :) However he will soon get another problem when he tries to do `1 + n2` (he should really remove those conversion functions. They will get into the way).
Johannes Schaub - litb
One thing at a time, I suppose. :)
Bill
A: 

You never declare operator + in number.h, you only define it in number.cpp - therefore, when you include number.h in main.cpp, it doesn't know where to go to find operator +.

You must put the declaration of operator + in number.h, outside of the class, then define it in number.cpp

Matt
Yep, tried that.. didn't quite work. But I figured it out.. I had to forward declare the struct before forward declaring the operator+
David Lazell
@David: Did you try putting operator+ after Number, instead of before it?
Bill
no, but I just did and that works also
David Lazell
A: 

One other thing to note with your code before you go back to us with a very similar question: Better remove the operator int and operator double functions. They will cause you major headache. Let's make a few examples:

Number a, b;

1 + b;
// ambiguous: operator+(int, int) or 
//            operator+(Number, Number) ?

// did you intend to use those for this case?
float x = a; 
// ambiguous: from int -> float or
//                 double -> float ?

In the original situation you had, your addition was ambiguous, because there were operator+(double, double) and operator+(int, int) builtin operators considered and they were equally well. Others solved that problem. But before you start and run into these other problems, better remove the conversion functions and insert explicit functions like asDouble or something similar.

Johannes Schaub - litb
This problem came from a Fraction class I wrote that used dynamically allocated cstrings for the numerator and denominator, just as an exercise in overloading. I managed to get it exception safe with no leaks. The err msg threw me off though(from not declaring it in number.h). The original idea was to be able to call the ctor with a double, which was converted, and either one or two ints which would be converted. I also wanted to be able to assign the fraction to an int or double variable, hence the conversion functions. But as you said, I can't do n2 = n1 +1. Can't have it both ways it seems.
David Lazell
I was hoping I could do "const Number operator + (int i, const Number " and similar functions to disambiguate(sp?) but that doesn't work. And float x=a is what what was intended and that does work.
David Lazell
@David, well assigning to `float` will cause an ambiguity because both `int` and `double` convert equally well to `float`. If this still works, it's a bug (or non-conformant behavior) in your compiler. If you add a `operator+(int, Number)`, it should work with `1 + n`, but then it will still fail with `1L + n` (first operand is `long`). Overload resolution isn't easy to work around like that. Best remove the conversion functions - that's all i can recommend you :)
Johannes Schaub - litb
I misread, yes float x=a is ambiguous, it is double x=a that works as intended. Perhaps you can tell me if there is a way to get n2=n1+1 working without explicit calls to the constructor?
David Lazell
Ok I will take your advice and not use the conversions when I have to do something like this again. Thanks.
David Lazell
Ok, I forgot to declare all the different operator+ overrides.. now that I have declared them everything works fine.. the only problem is the large number of operator+ overrides I have to do.
David Lazell
A: 

Personally I like it better to declare the operators inside the class:

struct Number
{
    int num;
    Number(int n=0,int d=1) {num = n/d;}
    operator int() {return num;}
    operator double() {return num*1.0;}
    Number operator+(const Number &arg) const;
};

and then:

Number Number::operator+(const Number &arg)
{
  ...
}
Frederik Slijkerman
Well the class it came from I wanted to be able to do n2=1+n1 in addition to n2=n1+1; Other that that I agree.
David Lazell
-1 for, it's not a good practice to make operator+ a member function. Again, in this case operator+ should be returning const Number and not Number.
Jagannath
@Jagannath: I'm new to C++, could you please explain the pitfalls of making it a member function?
dreamlax
This site has some good info on operator overloading guidelines:http://web.cecs.pdx.edu/~karlaf/CS202_Fall04/OpOvGuide.html
David Lazell
@dreamlax: if you have it as a member function, then you can't use the expression 1 + Number(1); so, it is suggested to make it a non-member function and get it overloaded with different types of parameters.
Jagannath
A: 

Apart from other's answers to declare operator+ in the header file, I suggest you to have operator+= in your struct as well.

struct Number
{
// your other declarations.
Number& operator+=(const Number& other)
{
   this->num += other.num;
   return *this;
}
};

const Number operator+(const Number& lhs, const Number& rhs)
{
    Number ret(lhs);
    ret += rhs;
    return ret;
}

This way it is efficient to call x += y; instead of x = x + y;

Jagannath
actually i did something similar in the original class: "return Number(lhs)+=rhs;"
David Lazell