51

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;
}
jww
  • 97,681
  • 90
  • 411
  • 885
Xun Yang
  • 4,209
  • 8
  • 39
  • 68
  • related: http://stackoverflow.com/q/2437586/951890 – Vaughn Cato Apr 06 '13 at 16:20
  • 13
    It's not overridden if it's not virtual, `Derived::foo` rather _hides_ `Base::foo`. – dyp Apr 06 '13 at 16:21
  • 1
    This looks very much like a design problem. If `Derived` has its own version of `foo`, chances are it was **not** designed to behave correctly if someone outside the class calls the base version instead. – Pete Becker Apr 06 '13 at 18:39
  • Possible duplicate of [How to call a parent class function from derived class function?](https://stackoverflow.com/q/357307/608639) – jww Jun 02 '18 at 19:59

4 Answers4

79

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.

dyp
  • 38,334
  • 13
  • 112
  • 177
  • Your derived class foo hides base class foo. Does using a qualifier-id syntax in this case also works ? – nurabha Mar 31 '16 at 20:48
  • @nurabha Could you elaborate, please? I don't quite understand what your question is. – dyp Apr 01 '16 at 12:38
  • Actually base class foo is not overriden by derived class foo but it is hidden. if you point a base class pointer to derived object and make a call using this pointer to foo, base will be printed. Base* basePtrToDerived = &bar; basePtrToDerived->foo(); – nurabha Apr 01 '16 at 14:01
  • 1
    @nurabha Yes. Casting to base is another way to call `Base::foo`. Using a qualified-id to call a base class' function works irrespectively of what happens to that function in the derived class - it can be hidden, it can be overridden, it can be made private (by using a using-declaration), you're directly accessing the base class' function when using a qualified-id. – dyp Apr 01 '16 at 20:19
21

First of all Derived should inherit from Base.

 class Derived : public Base{

That said

First of you can just not have foo in Derived

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

class Derived : public Base{

}

int main(){
  Derived bar;
  bar.foo() // calls Base::foo()
  return 0;
}

Second you can make Derived::foo call Base::foo.

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

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

int main(){
  Derived bar;
  bar.foo() // calls Base::foo()
  return 0;
}

Third you can use qualified id of Base::foo

 int main(){
    Derived bar;
    bar.Base::foo(); // calls Base::foo()
    return 0;
 }
4

Consider making foo() virtual in the first place.

class Base {
public:
    virtual ~Base() = default;

    virtual void foo() { … }
};

class Derived : public Base {
public:
    virtual void foo() override { … }
};

However, this does the job:

int main() {
    Derived bar;
    bar.Base::foo();
    return 0;
}
  • It would probably be better to write it as `bar.Base::foo()` – Mankarse Apr 06 '13 at 16:17
  • 1
    @Mankarse TIL that is possible. –  Apr 06 '13 at 16:17
  • If you make foo() virtual, still need to call `bar.Base::foo();` to access the base class method right? – Xun Yang Apr 06 '13 at 16:23
  • @XunYang yes, you do. Virtuality is irrelevant in this situation, but I found it worth mentioning. –  Apr 06 '13 at 16:23
  • OK thanks! Actually I'm using a bunch of libraries that use a very generic function name `void Base1::begin(){\\initialization}`, `class Derived:public Base1, public Base2{...}; void Derived::begin(){\\initialization}`, so the architectural is sadly out of my reach :( And just trying to do a hackish test here :) – Xun Yang Apr 06 '13 at 16:28
  • virtual keyword used in your derived class is redundant – nurabha Mar 31 '16 at 20:46
0

An important [additional] note: you will still have compilation errors if Name Hiding occurs.

In this case, either utilize the using keyword, or use the qualifer. Additionally, see this answer as well.

#include <iostream>

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

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

int main()
{
  Derived bar;
  //bar.foo(true,true);      // error:    derived func attempted
  bar.foo(true);             // no error: derived func
  bar.Base::foo(true,true);  // no error: base func, qualified
  return 0;
}
Community
  • 1
  • 1
bunkerdive
  • 2,031
  • 1
  • 25
  • 28