Implementing an operator in a child class

Jan 26, 2010 at 1:43pm
Hi all,

First of all: I hope this is the right forum for this sort of question. If not, feel free to move it.

i'm having to classes (say: CFoo and CBar), where CFoo is a superclass of CBar. Assume the operator "==" is overloaded in CFoo, and i want to overload in CBar, too.
The Question is: How do i call the "==" operator of CFoo in the "==" operator implementation of CBar?

One might consider calling
((CFoo*)this)->operator==(other);,
but this solution has a major drawback: the == operator of CFoo has to be not virtual. Also this is a rather ugly piece of code.

Has anyone a hint to do this better, in the best case without even knowing the names of the superclass(es) (like calling super.methodname() in Java)?

Cheers, TheBear
Last edited on Jan 26, 2010 at 1:44pm
Jan 26, 2010 at 2:07pm
I assume with superclass you mean base class.
You can try with CFoo::operator == ( other )
BTW is == defined inside CFoo or is it an external function?
Do you need CBar's == the same as CFoo's == ?
Jan 26, 2010 at 2:37pm
Hi Bazzy,

thanks for the answer. CFoo::operator== works fine, and is acceptable regarding readability.

The operator is defined as a member of CFoo. The == operator of CBar should do the following:
Two CBars are equal iff they are equal as CFoos and the additional data defined in CBar is equal.

I also rechecked my claim that the solution from above works only if CFoo::operator== is not virtual; it is not true. It appears that the keyword virtual has no effect on operator==, as the appended example shows (check the last 2 lines of main, B::operator== is not called. Compiler was g++ 4.4.1 (ubuntu).). Any recommendations how to achieve polymorphism in this case?

Cheers TheBear

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>

class A
{
	public:
		int a;
		virtual bool operator==(const A& other)
		{
			std::cout << "== of A" << std::endl;
			std::cout << "Value of this->a: " << a << std::endl;
			std::cout << "Value of other.a: " << other.a << std::endl;
			return other.a == a;
		}
};

class B : public A
{
	public:
		int b;
		virtual bool operator==(const B& other)
		{
			std::cout << "== of B" << std::endl;
			std::cout << "Value of this->b: " << b << std::endl;
			std::cout << "Value of other.b: " << other.b << std::endl;
			return (other.b == b) && (CFoo::operator==(other));
		} 
};

int
main(int argc, char** args)
{
	A a1, a2;
	B b1, b2;

	a1.a = 15;
	a2.a = 15;
	std::cout << (a1 == a2) << std::endl << std::endl;
	a2.a = 16;
	std::cout << (a1 == a2) << std::endl << std::endl;

	b1.a = 1;
	b2.a = 1;
	b1.b = 12;
	b2.b = 12;
	std::cout << (b1 == b2) << std::endl << std::endl;
	b2.b = 13;
	std::cout << (b1 == b2) << std::endl << std::endl;
	b2.b = 12;
	b2.a = 2;
	std::cout << (b1 == b2) << std::endl << std::endl;

	A* a3 = &b1;
	std::cout << ((*a3) == b1) << std::endl << std::endl;
	return 0;
}


Jan 26, 2010 at 2:54pm
It appears that the keyword virtual has no effect on operator==

Notice that B == is not the same as A == :
1
2
bool operator==(const A& other)
bool operator==(const B& other)
Parameter types are different so B == will overload A ==, it won't override it
Jan 26, 2010 at 4:35pm
This is actually somewhat of an interesting problem.

My approach would be to just have A ==. Don't make it virtual and don't put it in derived classes. Instead, have A == call a private virtual "Compare" function which compares child types, but only if the types are the same.

The derived B::Compare would need to downcast to the appropriate type.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class A
{
public:
    int a;
    bool operator==(const A& other) const
    {
        // make sure the types are the same
        if(typeid(*this) != typeid(other))
            return false;
            
        // if they are the same, then compare them
        return Compare(other);
    }
    
private:
    virtual bool Compare(const A& other) const
    {
        // compare A members
        return a == other.a;
    }
};

class B : public A
{
public:
    int b;
    // no == operator

private:
    virtual bool Compare(const A& other) const // note it takes an A parameter
    {
        // compare A members (and any other parents if multiple parents)
        if(!A::Compare(other))
            return false;
            
        // compare B members
        // safe to static cast because A::== already confirmed the type
        const B& otherb = static_cast<const B&>(other);
        
        return b == otherb.b;
    }
};
Last edited on Jan 26, 2010 at 4:35pm
Jan 26, 2010 at 6:17pm
Hi again,

Bazzi: I should have seen that.

Disch: This really seems to be a good way to implement the desired behavior, thanks.
Jan 26, 2010 at 9:43pm
Yes, inheritance and operators don't mix too well.

Although the above works, the two "issues" with are that I cannot compare two B instances in the
same way as two A instances (can't compare B's at all; can use operator== on As), and that
in general it is not terribly maintainable.
Jan 27, 2010 at 11:45am
Hi jsmith,

what do you mean? Comparison of 2 Bs works very well, and it works as expected: simply use the operator ==. Actually, when you have a common base class for all classes in your hierarchy (like Object in Java), you can compare any pair of objects from this hierarchy.

I also consider this solution to be somewhat maintainable (though this could be better), as in every class, there is only class specific code to be implemented (within the compare-method).

There is only one thing i could not solve: It appears, when the class hierarchy has a dreaded diamond in it, i.e. the following situation appears:
1
2
3
4
5
6
7
8
9
10
11
class A
{
public:
     operator==(const A& other);
//...
protected:
    virtual bool compare(const A& other) const;
};
class B : public virtual A {/*...*/};
class C : public virtual A {/*...*/};
class D : public B, public C {/*...*/};


When I try to implement this in this way, i get some errors like the following (gcc 4.4.1, ubuntu version):
1
2
FooBar.cpp: In member function ‘virtual bool C::compare(const A&) const’:
FooBar.cpp:58: error: cannot convert from base ‘A’ to derived type ‘C’ via virtual base ‘A’


However, this seems more to be an error/misunderstanding of multiple inheritance to me, since i have not gotten very involved in that ever before. Also, its likely to not appear in my case.

TheBear
Topic archived. No new replies allowed.