2

I'm having some issues understanding this concept. In the main.cpp file, we have a function as follows:

void TestComparison()
{
    MyFloat X, Y;

    cout << "\n\n============  Testing \"==\"  for MyFloat  ================\n";

    do
    {
        cout << "\nEnter X  ==> ";
        X.Read();
        cin.ignore(1000, '\n');             //  Discard all chars in input stream.
        cout << "\nEnter Y  ==> ";
        Y.Read();
        cin.ignore(1000, '\n');             //  Discard all chars in input stream.

        cout << "\n\n";

        if ( X == Y )
        {
            X.Write(); cout << " is equal to "; Y.Write();
        }
        else
        {
            X.Write(); cout << " is NOT equal to "; Y.Write();
        }
    }
    while ( SpaceBarToContinue() );
}

This is the class I'm writing:

class MyFloat
{
    enum {MAXDIGIT=20};
    char Number[MAXDIGIT+1];
    char NumberOfDigits;

public:

    friend void AssignValue(MyFloat& X);//remove after the program works

    MyFloat();

    int Digits();
    int MaxDigits();
    void Read();
    void Write();

    MyFloat operator + (MyFloat x);
    int operator== (MyFloat x);
};

Here is my == overload function stub:

int MyFloat::operator== (MyFloat x)
{
    int Flag=0;

    return 1;
}

The only purpose of this is to compare two an array of objects X and Y. They are passed into a == overloaded function. I'm supposed to write the algorithm that compares them. I know how to write the algorithm that compares these two character arrays, thats not the issue, but what I'm failing to understand is how both X and Y get into the the overloaded function to compare them? In the main, the code ( X == Y ) is used to obtain a 0 or 1. How are X and Y passed into the function?

For instance, I would assume my function stub would need to be rewritten with 2 parameters:

int MyFloat::operator== (MyFloat x, MyFloat y)
{
    int Flag=0;

    return 1;
}

But doing this produces an error back in the main during the function call of ( X == Y ) that states 'Overload "operator==" must be a binary operator (has 3 parameters)'

So I'm totally confused on how to get both Objects of MyFloat into the function to compare them. I'm still fairly new to programming (5-6 months of learning), any plain and simple answers are greatly appreciated.

fredmaggiowski
  • 2,232
  • 3
  • 25
  • 44
JosephTLyons
  • 2,075
  • 16
  • 39
  • 1
    `operator==` should really return a `bool`, not `int`. – PaulMcKenzie Mar 03 '16 at 22:49
  • Possible duplicate of [overloaded 'operator+' must be a unary or binary operator error](http://stackoverflow.com/questions/13554320/overloaded-operator-must-be-a-unary-or-binary-operator-error) – fredmaggiowski Mar 03 '16 at 22:51
  • 1
    look at this answer: http://stackoverflow.com/questions/13554320/overloaded-operator-must-be-a-unary-or-binary-operator-error You've declared the operator as a class member, thus it accepts an implicit member. You should implement it as a non-member of the class MyFloat – fredmaggiowski Mar 03 '16 at 22:53
  • Off topic: this comment is a lie: `cin.ignore(1000, '\n'); // Discard all chars in input stream.` There could be more than 1000 characters on the line and there could be more than one line in the stream. what you probably want to handle the first case is `cin.ignore(numeric_limits::max(), '\n');` – user4581301 Mar 03 '16 at 23:05
  • Side note: your Read / Write member function are not very flexible. You should probably prefer overriding `operator <<` and `operator >>` so that you can write: `cin >> x;` and `cout << x;` instead of `x.Read();` and `x.Write();`. It's not only easier to use, it also allow using other streams to read from files, strings ... – Colin Pitrat Mar 03 '16 at 23:05
  • @ColinPitrat, Its not my choice, the read() and write() functions are exactly what we are being asked to write. In my 101 class, we had to write the programs on our own, but in this 201 class, we are given algorithms and pseudocode to convert to code. The read function was already created by my professor in pseudocode, so I had to use it. I appreciate the advice though. – JosephTLyons Mar 03 '16 at 23:08
  • @user4581301, yeah, I should've deleted that comment. That comment wasn't actually meant to be read by anyone else buy me. It wasn't written correctly. – JosephTLyons Mar 03 '16 at 23:09
  • Thanks for all the comments guys. Quick note, what would we use if we wanted to return a custom data type with an overloaded operator? I noticed most of you guys are saying it needs to return a Bool, but about the addition operator overloading function? That would need to return an object of MyFloat data type, right? – JosephTLyons Mar 04 '16 at 03:53
  • Yes, `operator+` or other arithmetic operator would return a `MyFloat&`. And `operator=` (assignment) would return a `const MyFloat&`. You can even provide multiple versions of an operator taking different parameters types (e.g: to allow `MyFloat + int`, although an implicit constructor may be a simpler way in this specific case). There is flexibility in the signature you choose for operator overloading as long as it provides the correct functionality. But there are also widely adopted usages (& wisdom) that are justified. Unless you have a good reason to devy from this wisdom, follow it :-) – Colin Pitrat Mar 04 '16 at 07:23
  • When I say `as long as it provides the correct functionality`, it means that if the code `a == b` which really means `a.operator==(b)` can compile then the compiler will accept it and use your operator. So you could have `operator==` return anything. It's just bad practice because users of your class will expect `operator==` to return a `bool`. – Colin Pitrat Mar 04 '16 at 07:25

3 Answers3

3

When you write:

if(a == b)

what it really means is:

if(a.operator==(b))

So in your method:

bool MyFloat::operator==(const MyFloat &x) const
{
    // x is b in call above
    // (*this) is a in call above

    // Your class invariant should guarantee this:
    // assert(x.NumberOfDigits < MAX_DIGITS);

    // In the scope of your class' methods:
    //   NumberOfDigits corresponds to this->NumberOfDigits
    //   Number corresponds to this->Number
    if(x.NumberOfDigits != NumberOfDigits) return false;
    // Same as: if(x.NumberOfDigits != this->NumberOfDigits) return false;
    return strncmp(x.Number, Number, NumberOfDigits) == 0;
    // Same as: return strncmp(x.Number, this->Number, this->NumberOfDigits) == 0;
}

Note that I changed the signature of your method. The correct signature returns a bool and takes a const (because you don't want to change the parameter) reference (avoid copying a big object) as parameter. The method is (and must be) const because it's not supposed to modify the object and it must be callable on a const object.

Note that it is possible to define the operator as a non-member function (i.e outside of the class) with the following signature:

bool operator==(const MyFloat &a, const MyFloat &b)
Colin Pitrat
  • 1,992
  • 1
  • 16
  • 28
  • 1
    Years of practice. Only remaining issue I'd bring up is with the assert, but that one is ideological. Invalid size should be should be tested for and rejected when constructed or set so that the object never gets in an illegal state and you don't have to test on a get. Usually more gets than sets. – user4581301 Mar 03 '16 at 23:32
  • Yeah, I hesitated between putting it for real or just as a comment. I don't really like the usage of assert either, it's just to highlight the class invariant and the fact that it's needed for `strncmp` to not be risky. – Colin Pitrat Mar 04 '16 at 07:18
  • Well, now I'm entirely confused. I emailed my professor and he said to do the function overloading without using *this, and that only one object will be passed in via a parameter. So I'm lost, I have no idea how the other object is being passed in if we aren't supposed to use *this. – JosephTLyons Mar 05 '16 at 20:10
  • You can access the members without using `this`. In the method, `NumberOfDigits` is equivalent to `this->NumbefOfDigits` so maybe that's what your professor meant by "without using (*this)": it means not using it explicitely. I update my answer with this information. – Colin Pitrat Mar 06 '16 at 08:29
2

You should use this pointer. For more information: Source

bool MyFloat::operator==(const MyFloat& x) const
{
    for(int i = 0; i < x.MaxDigits; ++i)
    {
        if(x[i] != (*this)[i])
            return false;
    }
    return true;
}
-1

member functions (including overloaded operators) have an implicit this parameter passed in. In your case since you are using a member version of operator== you should only need one parameter the other is this.

YoungJohn
  • 946
  • 12
  • 18
  • Down voter care to comment. How can I improve this answer? – YoungJohn Mar 03 '16 at 22:47
  • I'm not the downvoter, but maybe your answer has been downvoted because it could be improved, with example code or some reference. By the way it is a working solution, thus it's pretty unfair :( – fredmaggiowski Mar 03 '16 at 22:56