4
#include <iostream>

class Foo {
public:
    int m_foo;
    Foo(int a_foo) : m_foo(a_foo) {}

protected:
    bool operator==(const Foo& a) const {
        std::cout << "Foo: " << m_foo << " == " << a.m_foo << '\n';
        return m_foo == a.m_foo;
    }
};

class Bar : public Foo {
public:
    int m_bar;
    Bar(int a_foo, int a_bar) :
        Foo(a_foo),
        m_bar(a_bar)
    {}

    bool operator==(const Bar& a) const {
        std::cout << "Bar: " << m_foo << ", " << m_bar << " == " << a.m_foo << ", " << a.m_bar << '\n';
        return (const Foo&)*this == (const Foo&)a &&
               m_bar             == a.m_bar;
    }
};

int main() {
    Bar a(1, 1);
    Bar b(1, 2);
    Bar c(2, 2);

    std::cout << (a == a) << '\n';
    std::cout << (a == b) << '\n';
    std::cout << (a == c) << '\n';

    return 0;
}

In my real code Foo is a class which can be instantiated but should not be allowed to use operator== and so I made it protected. I am getting a compiler error from doing this:

foo.cpp: In member function ‘bool Bar::operator==(const Bar&) const’:
foo.cpp:9:7: error: ‘bool Foo::operator==(const Foo&) const’ is protected
  bool operator==(const Foo& a) const {
       ^
foo.cpp:25:43: error: within this context
   return (const Foo&)*this == (const Foo&)a &&
                                           ^

Why is this not allowed? Shouldn't the derived class be able to use the protected method?

asimes
  • 5,749
  • 5
  • 39
  • 76
  • 2
    `return (const Foo&)*this == (const Foo&)a` -- Not sure, but that `==` doesn't seem to be operating on the base class. It's two independent objects, `*this` and `a`. The answer given by @MichaelBurr actually makes use of the base class, `Foo::` in the call. – PaulMcKenzie Apr 18 '17 at 20:32
  • @PaulMcKenzie, This kind of makes sense, it is almost as if it were more like the `operator==(const Foo& l, const Foo& r)` signature but I would have thought `(const Foo&)*this` would have produced a `Foo` and then its method would be used – asimes Apr 18 '17 at 20:37
  • @PaulMcKenzie, I thought about this a bit more, and decided that because I did not define a two object equality operator that there should not be a function / method to compare the two objects. Still confused though – asimes Apr 18 '17 at 21:20
  • I think http://stackoverflow.com/questions/16785069/why-cant-a-derived-class-call-protected-member-function-in-this-code has the answer for your question. – Dinesh Maurya Apr 19 '17 at 03:49
  • @DineshMaurya, Yes, it makes sense now, thank you – asimes Apr 19 '17 at 05:01

1 Answers1

3

I can't answer why (yet), but this alternative syntax does what you want:

return Foo::operator==(a) &&  (m_bar == a.m_bar);
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • I still would like to know the answer but for all practical purposes this works, +1 – asimes Apr 18 '17 at 20:23
  • I'd have to refresh my memory on the details, but I'm pretty sure this has to do with rules regarding ADL (Argument Dependent Lookup aka Koenig lookup). – Michael Burr Apr 18 '17 at 20:31
  • Dinesh Maurya pointed out the why in the comments, going to go ahead and accept your answer because it is the solution to the problem – asimes Apr 19 '17 at 05:03