Call base class method from derived class object

c++, inheritance

Solution

You can always(*) refer to a base class's function by using a qualified-id:

#include <iostream>

class Base{
  public:
    void foo(){std::cout<<"base";}
};

class Derived : public Base
{
  public:
    void foo(){std::cout<<"derived";}
};

int main()
{
  Derived bar;
  //call Base::foo() from bar here?
  bar.Base::foo(); // using a qualified-id
  return 0;
}

[Also fixed some typos of the OP.]

(*) Access restrictions still apply, and base classes can be ambiguous.

If `Base::foo` is not `virtual`, then `Derived::foo` does not override `Base::foo`. Rather, `Derived::foo` hides `Base::foo`. The difference can be seen in the following example:

struct Base {
   void foo()         { std::cout << "Base::foo\n"; }
   virtual void bar() { std::cout << "Base::bar\n"; }
};

struct Derived : Base {
   void foo()         { std::cout << "Derived::foo\n"; }
   virtual void bar() { std::cout << "Derived::bar\n"; }
};

int main() {
    Derived d;
    Base* b = &d;
    b->foo(); // calls Base::foo
    b->bar(); // calls Derived::bar
}

(`Derived::bar` is implicitly virtual even if you don't use the `virtual` keyword, as long as it's signature is compatible to `Base::bar`.)

A qualified-id is either of the form `X :: Y` or just `:: Y`. The part before the `::` specifies where we want to look up the identifier `Y`. In the first form, we look up `X`, then we look up `Y` from within `X`'s context. In the second form, we look up `Y` in the global namespace.

An unqualified-id does not contain a `::`, and therefore does not (itself) specify a context where to look up the name.

In an expression `b->foo`, both `b` and `foo` are unqualified-ids. `b` is looked up in the current context (which in the example above is the `main` function). We find the local variable `Base* b`. Because `b->foo` has the form of a class member access, we look up `foo` from the context of the type of `b` (or rather `*b`). So we look up `foo` from the context of `Base`. We will find the member function `void foo()` declared inside `Base`, which I'll refer to as `Base::foo`.

For `foo`, we're done now, and call `Base::foo`.

For `b->bar`, we first find `Base::bar`, but it is declared `virtual`. Because it is `virtual`, we perform a virtual dispatch. This will call the final function overrider in the class hierarchy of the type of the object `b` points to. Because `b` points to an object of type `Derived`, the final overrider is `Derived::bar`.

When looking up the name `foo` from `Derived`'s context, we will find `Derived::foo`. This is why `Derived::foo` is said to hide `Base::foo`. Expressions such as `d.foo()` or, inside a member function of `Derived`, using simply `foo()` or `this->foo()`, will look up from the context of `Derived`.

When using a qualified-id, we explicitly state the context of where to look up a name. The expression `Base::foo` states that we want to look up the name `foo` from the context of `Base` (it can find functions that `Base` inherited, for example). Additionally, it disables virtual dispatch.

Therefore, `d.Base::foo()` will find `Base::foo` and call it; `d.Base::bar()` will find `Base::bar` and call it.

Fun fact: Pure virtual functions can have an implementation. They cannot be called via virtual dispatch, because they need to be overridden. However, you can still call their implementation (if they have one) by using a qualified-id.

#include <iostream>

struct Base {
    virtual void foo() = 0;
};

void Base::foo() { std::cout << "look ma, I'm pure virtual!\n"; }

struct Derived : Base {
    virtual void foo() { std::cout << "Derived::foo\n"; }
};

int main() {
    Derived d;
    d.foo();       // calls Derived::foo
    d.Base::foo(); // calls Base::foo
}

Note that access-specifiers both of class members and base classes have an influence on whether or not you can use a qualified-id to call a base class's function on an object of a derived type.

For example:

#include <iostream>

struct Base {
public:
    void public_fun() { std::cout << "Base::public_fun\n"; }
private:
    void private_fun() { std::cout << "Base::private_fun\n"; }
};

struct Public_derived : public Base {
public:
    void public_fun() { std::cout << "Public_derived::public_fun\n"; }
    void private_fun() { std::cout << "Public_derived::private_fun\n"; }
};

struct Private_derived : private Base {
public:
    void public_fun() { std::cout << "Private_derived::public_fun\n"; }
    void private_fun() { std::cout << "Private_derived::private_fun\n"; }
};

int main() {
    Public_derived p;
    p.public_fun();        // allowed, calls Public_derived::public_fun
    p.private_fun();       // allowed, calls Public_derived::public_fun
    p.Base::public_fun();  // allowed, calls Base::public_fun
    p.Base::private_fun(); // NOT allowed, tries to name Base::public_fun

    Private_derived r;
    r.Base::public_fun();  // NOT allowed, tries to call Base::public_fun
    r.Base::private_fun(); // NOT allowed, tries to name Base::private_fun
}

Accessibility is orthogonal to name lookup. So name hiding does not have an influence on it (you can leave out `public_fun` and `private_fun` in the derived classes and get the same behaviour and errors for the qualified-id calls).

The error in `p.Base::private_fun()` is different from the error in `r.Base::public_fun()` by the way: The first one already fails to refer to the name `Base::private_fun` (because it's a private name). The second one fails to convert `r` from `Private_derived&` to `Base&` for the `this`-pointer (essentially). This is why the second one works from within `Private_derived` or a friend of `Private_derived`.

Problem

How can I call a base class method which is overridden by the derived class, from a derived class object? ``` class Base{ public: void foo(){cout<<"base";} }; class Derived:public Base{ public: void foo(){cout<<"derived";} } int main(){ Derived bar; //call Base::foo() from bar here? return 0; } ```

Original source

Related problems