3

I don't understand why I need to redefine an overrided base class method.

Here, if I comment the foo() method in the derived class, it does not compile.

Thanks for your explanations.

class Base {
public:
    void foo() {
    }
};

class Derived: public Base {
public:
#define compile_ok
#ifdef compile_ok
    // if this method is commented, it does not compile
    void foo() {
        Base::foo();
    }
#endif
    void foo(int i) {
    }
    void test() {
        foo();
        foo(1);
    }
};

void testOverride() {
    Derived d;
    d.test();
}
  • yes, already asked in: [c-override-overload-problem](http://stackoverflow.com/questions/1484641/c-override-overload-problem) [function-with-same-name-but-different-signature-in-derived-class](http://stackoverflow.com/questions/411103/function-with-same-name-but-different-signature-in-derived-class) [c-overload-resolution](http://stackoverflow.com/questions/72010/c-overload-resolution) – armand nissim bendanan Mar 20 '13 at 00:00

3 Answers3

3

Your foo(int) hides the base class name. Fix it like this:

class Derived: public Base {
public:
    using Base::foo;
    void foo(int i) {
    }
    void test() {
        foo();
        foo(1);
    }
};
sehe
  • 374,641
  • 47
  • 450
  • 633
  • thanks a lot, it works! But I still don't understand why we need this using clause. but it's ok – armand nissim bendanan Mar 19 '13 at 13:01
  • Well, basically, it's because of the standard. A name explicitely declared in the derived "_namespace_" supersedes the implicitly _inherited_ name(s). This is the whole reason. – sehe Mar 19 '13 at 13:13
3

Your declaration of foo taking a single int argument will hide any functions named foo in Base. You can bring a hidden name from Base like so:

class Derived: public Base {
public:
    using Base::foo; // Pulls foo from Base
    void foo(int i) {
    }
    void test() {
        foo();
        foo(1);
    }
};
Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
1

The answer, as others have already said, is that the foo in the derived type hides the foo in the base type. To extend a bit on what that means the problem is that lookup has a set of rules, and the compiler must apply those rules until it finds the identifier. Once it finds the name, it won't continue looking for better matches, it will try to use what it sees.

When inside Derived::test you type foo(), the compiler must resolve foo, which might be anything (type, [member] variable, [member] function...). To do so it starts looking what is available inside Derived::test, and there is no foo declared there. It then widens the search to the full type Derived and it finds that there is a member function foo. At this point it stops *. If it had not find Derived::foo(int) it would keep expanding the search to the bases, then the namespace, then other namespaces...

* In this particular case, because the identifier resolves to a function an extra step is taken as ADL kicks in (or rather would kick in if there were arguments of non-fundamental types passed to the function).

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489