3
class Eq
{
public:
    virtual bool operator==(Eq operand) = 0;
};

class Day : public Eq
{
public:
    enum DAY
    {
        Monday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday,
        Sunday
    } day;
    Day(DAY init_day) : day(init_day){}
    bool operator==(Day operand)
    {
        return day == operand.day;
    }
};

int main()
{
    Day d1(Day::Monday);
    Day d2(Day::Monday);
    d1 == d2;
    return 0;
}

This is the code which I trying to implement. Class Eq works like as interface of JAVA. It has only one member function, operator==. Operator== takes one operand which is same type with the class which is deriving Eq class. For example, class Day derives Eq, so it have to implement operator== which is taking Day type parameter.

And there is the problem. First, both operator== functions have different signatures. So the compiler thinks they are not same functions, but overrided functions. Second, if any function in this code takes Eq class parameter, then compiler makes error because instance of the abstract class is not available.

So this is the question. How can I make operator== function in T class to take T class parameter, where T is implementation of Eq class?

Mossid
  • 183
  • 1
  • 9
  • 1
    Is this what you're trying to achieve, or it's an example? I mean, you don't need to make `operator==` pure virtual to force the user to implement its own `operator==`. As there's no default `operator==`, `d1 == d2` will not compile, if `Day` does not implement `operator==`. – Kiril Kirov Feb 16 '15 at 16:13
  • You should really learn to pass parameters by reference, not by value. – PaulMcKenzie Feb 16 '15 at 16:13
  • I agree with @KirilKirov If this is all what you are doing, don't bother with a base class here. Also make the operator a const function. – Neil Kirk Feb 16 '15 at 16:28

4 Answers4

3

You could introduce a type parameter T in Eq and derive Dayfrom Eq<Day> to enforce the desired signature of operator==.

Codor
  • 17,447
  • 9
  • 29
  • 56
2

you can use CRTP:

template <typename DerivedType>
class Eq
{
public:
    virtual bool operator==(DerivedType operand) = 0;
};

class Day : public Eq<Day>
{
public:
    enum DAY
    {
        Monday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday,
        Sunday
    } day;
    Day(DAY init_day) : day(init_day){}
    bool operator==(Day operand)
    {
        return day == operand.day;
    }
};
swang
  • 5,157
  • 5
  • 33
  • 55
  • 1
    At this point there really isn't much purpose in making the function virtual. – Dan Feb 16 '15 at 16:32
  • You probably don't want to pass parameters by value here. – quantdev Feb 16 '15 at 16:43
  • @Dan: you are right, but what if something wants to derive from Day and have a go at override ==. Anyway I was trying to modify as less as possible to make it work:) – swang Feb 16 '15 at 16:46
2

You can do this by sending in references instead.

class Eq
{
public:
    virtual bool operator==(Eq& operand) = 0; // Changed to reference
};

class Day : public Eq
{
public:
    enum DAY
    {
        Monday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday,
        Sunday
    } day;
    Day(DAY init_day) : day(init_day){}
    bool operator==(Eq& operand) // Changed to reference of Eq.
    {
        const Day* other = dynamic_cast<Day*> (&operand);
        if (other == nullptr) // Checking if the operand is of Day type.
            return false; // If not, those two objects cannot be the same.
        return day == other->day; // Do the comparison. 
        // Note the '->' instead of '.' since 'day' is a pointer.
    }
};

You are missing a few key points on how C++ works compared to Java (which I guess you are more familiar with).

  1. To do virtual overriding you have to have the same method signature.
  2. To avoid slicing you need to send references or pointers, not objects on the stack.
  3. Finally, it could be potentially very memory intensive to send values (compared to references or pointers).

Here are a couple of good links I found regarding how to do operator== overloading when dealing with inheritance. (They also talk about the public-non-virtual/non-public-virtual discussion.)

Equality Test for Derived Classes in C++

What's the right way to overload operator== for a class hierarchy?

Community
  • 1
  • 1
Mats Fredriksson
  • 19,783
  • 6
  • 37
  • 57
1

Your approach has two main flaws:

  • The signature of operator== for Day does not match the one of Eq so it won't work.
  • You pass operand of operator by value. THis means that there will be slicing (i.e. the object passed might loose all members that are not in Eq, here the day)

There are already nice template solutions proposed, which is very convenient for this kind of problems. For the sake of completeness, I propose you a templateless alternative.

First chance Eq:

class Eq
{
public:
    virtual bool operator==(Eq& operand) = 0;  // References passing doesn't slice
};

Then update its overriding in Day:

bool operator==(Eq& operand)
{
    if (dynamic_cast<Day*>(&operand))  // check if types compatible 
        return day == dynamic_cast<Day*>(&operand)->day;
    else return false;  // else the objects are different anyway
}

Finally you can test in main():

 ...
if (d1 == d2)  // check that result is as expected !
    cout << "Yes it works !";  
else cout << "Hhmmm..."; 
Christophe
  • 68,716
  • 7
  • 72
  • 138