C++ Overloading == to compare objects from different classes

Viewed 3929

For a lab, I had to overload the + operator to add objects from the same class and the == operator to compare objects from two different classes. The function to overload the == operator is giving me so much trouble (likely because I'm using it to compare the object areas of different classes). I've looked for a solution relentlessly, and I've tried all the suggestions found without success, so I'm forced to ask using my specific code:

// OBJECTIVES:
// Add areas of 2 circles
// Add areas of 2 rectangles
// Compare areas of a circle and a rectangle

#include <iostream>
using namespace std;

// **********************Header*********************
class circle
{
    friend bool operator==(const circle& ,
                           const circle&);
    friend circle operator+(const circle& , 
                            const circle&);
public:
    double radius, area;
    void calcArea();
};

class rect
{
    friend bool operator==(const rect& , 
                           const rect&);
    friend rect operator+(const rect& , 
                          const rect&);
public:
    double length, width, area;
    void calcArea();
};

void displayMenu();
// **************************************************

// **********************Program*********************
int main()
{
    int selection; // variable for menu selection

    circle firstCircle; // objects from circle class
    circle secondCircle;

    rect firstRect; // objects from rect class
    rect secondRect;

    do {
        displayMenu();
        cin >> selection;
        cout << endl;

        if (selection == 1) // add area of 2 circles
        {
            firstCircle.calcArea();
            secondCircle.calcArea();
            circle thirdCircle = firstCircle + secondCircle;

            cout << "The sum of your two circles is: " ;
            cout << thirdCircle.area;
            cout << endl;
        }

        else if (selection == 2) // add area of 2 rectangles
        {
            firstRect.calcArea();
            secondRect.calcArea();
            rect thirdRect = firstRect + secondRect;

            cout << "The sum of your two rectangles is: " ;
            cout << thirdRect.area;
            cout << endl;

        }

        else if (selection == 3) // compare areas of a circle and a rectangle
        {
            firstCircle.calcArea();
            firstRect.calcArea();

            if (firstCircle.area == firstRect.area)
            {
                cout << "The area of your circle is equal to that of your rectangle." << endl;
            }
            else
            {
                cout << "The area of your circle is not equal to that of your rectangle." << endl;
            }
        }

        else if (selection == 4) // exit program
        {
            return 0;
        }

        else
        {
            cout << "Please enter a valid selection.";
            cout << endl;
            continue;
        }
    } while (1);

    return 0;
}
// **************************************************

// ******************Implementation******************
void circle::calcArea() // compute circle area
{
    cout << "Enter a radius: ";
    cin >> radius;

    area = 3.14159265359 * radius * radius;
}

void rect::calcArea() // compute rectangle area
{
    cout << "Enter a length: ";
    cin >> length;
    cout << "Enter a width: ";
    cin >> width;

    area = length * width;
}

bool operator==(const circle& firstCircle, // compare areas of objects
                const rect& firstRect)  // from different classes
{
    return (firstCircle.area == firstRect.area && 
            firstCircle.area == firstRect.area);
}

circle operator+ (const circle& firstCircle, // overload + for circle class
                    const circle& secondCircle)
{
    circle circleSum;

    circleSum.radius = firstCircle.radius + secondCircle.radius;
    circleSum.area = firstCircle.area + secondCircle.area;

    return circleSum;
}

rect operator+ (const rect& firstRect, // overload + for rect class
                    const rect& secondRect)
{
    rect rectSum;

    rectSum.length = firstRect.length + secondRect.length;
    rectSum.width = firstRect.width + secondRect.width;
    rectSum.area = firstRect.area + secondRect.area;

    return rectSum;
}

void displayMenu() // menu options
{
    cout << endl;
    cout << "What would you like to do?" << endl;
    cout << "1. Add the area of 2 circles."<< endl;
    cout << "2. Add the area of 2 rectangles."<< endl;
    cout << "3. Compare the area of a circle and a rectangle."<< endl;
    cout << "4. Exit.";
}
// **************************************************

Right now, I'm not using the overloaded == to compare the rectangle and circle areas because then I get a lot of compiler errors. Any help you guys can offer me to be able to change firstCircle.area == firstRect.area to firstCircle == firstRect would be so greatly appreciated.

2 Answers

There is a number of approaches to write a comparison operator you want. The simplest way, without interventing your class code, is just to implement a couple of nonmember operators:

bool operator==(const circle& c, const rect& r) { return r.area == c.area; }
bool operator==(const rect& r, const circle& c) { return c.area == r.area; }

You might put them in you source file above the main function, or to a separate header file. Note that they don't need to be friends of circle and rect, as area member is public.

Another way is to write member functions, but first we need to fix your existing comparison operators:

class circle
{
public:
    bool operator==(const circle& other) const { return area == other.area; }

    // ...skipped...
};

How and why is it different from your version?

  1. It's a member function which compares this to other, taking only one argument.
  2. It's public to be called from outside of circle class
  3. It's const-qualified, because it needs only a lookup of class data without modifications.

Also const qualifier allows you to compare const objects like this:

const circle c1 = getSomeCircle();
const circle& c2 = otherCircle;
c1 == c2; // Note: statement has no effect, despite it's syntax is correct.
c2 == c1;

Non-const-qualified comparison would fail to compile. All in all, this is the most idiomatic way to write comparison operators in C++.

Finaly, let's add circle to rect comparison:

class rect;

class circle
{
public:
    bool operator==(const circle& other) const { return area == other.area; }
    bool operator==(const rect&) const;

    // ...skipped...
};

class circle { /* class definition skipped */ };

bool operator==(const rect& r) const { return area == r.area; }

Here first we declared the rect class. When class is declared but not defined (which is forward declaration), we can use pointers ant references to it's instances, but not instances themselves. One of the reasons we can't use instances is that class size is unknown before it's definition.

Then we declare member operator== accepting a reference to forward-declared class, and finally after rect definition we can implement the operator.

rect to circle comparison may be implemented all the same way.

Operator overloading can be overloaded like below.

#include <iostream>
using namespace std;

class rect;

class circle
{
    friend bool operator==(const circle&,
        const circle&);
    //friend circle operator+(const circle&,
    //  const circle&);
public:
    double radius, area;
    //void calcArea();
public:
    friend bool operator == (const circle&, const rect&);
    double getArea()const { return area; }
};

class rect
{
    friend bool operator==(const rect&,
        const rect&);
    //friend rect operator+(const rect&,
    //  const rect&);
public:
    double length, width, area;
    //void calcArea();
public:
    friend bool operator == (const rect&, const circle&);
    double getArea() const{ return area; }
};

int main(int argc, char *argv[]) {
    circle c;
    rect r;
    if (c == r) {
        cout << "It was a miracle a random circle is equal to a random rectangle in size!!!" << endl;
    }
    return 0;
}

bool operator == (const circle &c1, const circle &c2) {
    return c1.getArea() == c2.getArea();
}

bool operator == (const rect &r1, const rect &r2) {
    return r1.getArea() == r2.getArea();
}

bool operator == (const circle &c, const rect &r) {
    return c.getArea() == r.getArea();
}

bool operator == (const rect &r, const circle &c) {
    return c.getArea() == r.getArea();
}
Related