Alex
Alex

Reputation: 15353

Can I call a base class's virtual function if I'm overriding it?

Say I have classes Foo and Bar set up like this:

class Foo
{
public:
    int x;

    virtual void printStuff()
    {
        std::cout << x << std::endl;
    }
};

class Bar : public Foo
{
public:
    int y;

    void printStuff()
    {
        // I would like to call Foo.printStuff() here...
        std::cout << y << std::endl;
    }
};

As annotated in the code, I'd like to be able to call the base class's function that I'm overriding. In Java there's the super.funcname() syntax. Is this possible in C++?

Upvotes: 430

Views: 330686

Answers (8)

sth
sth

Reputation: 229914

In C++ you have to explicitly name the base class in calling the derived class method. This can be done from any method from the derived class. The override is a special case of the method of the same name. In Java there is no multi inheritance, so you can use super which will uniquely name the base class. The C++ syntax is like this:

class Bar : public Foo {
  // ...

  void printStuff() override {  // help the compiler to check
    Foo::printStuff(); // calls base class' function
  }
};

Upvotes: 553

Phil Jollans
Phil Jollans

Reputation: 3769

If there are multiple levels of inheritance, you can specify the direct base class, even if the actual implementation is at a lower level.

class Foo
{
public:
  virtual void DoStuff ()
  {
  }
};

class Bar : public Foo
{
};

class Baz : public Bar
{
public:
  void DoStuff ()
  {
    Bar::DoStuff() ;
  }
};

In this example, the class Baz specifies Bar::DoStuff() although the class Bar does not contain an implementation of DoStuff. That is a detail, which Baz does not need to know.

It is clearly a better practice to call Bar::DoStuff than Foo::DoStuff, in case a later version of Bar also overrides this method.

Upvotes: 4

Atif
Atif

Reputation: 77

Yes you can call it. C++ syntax for calling parent class function in child class is

class child: public parent {
  // ...

  void methodName() {
    parent::methodName(); // calls Parent class' function
  }
};

Read more about function overriding.

Upvotes: 0

joseAndresGomezTovar
joseAndresGomezTovar

Reputation: 819

check this...

#include <stdio.h>

class Base {
public:
   virtual void gogo(int a) { printf(" Base :: gogo (int) \n"); };    
   virtual void gogo1(int a) { printf(" Base :: gogo1 (int) \n"); };
   void gogo2(int a) { printf(" Base :: gogo2 (int) \n"); };    
   void gogo3(int a) { printf(" Base :: gogo3 (int) \n"); };
};

class Derived : protected Base {
public:
   virtual void gogo(int a) { printf(" Derived :: gogo (int) \n"); };
   void gogo1(int a) { printf(" Derived :: gogo1 (int) \n"); };
   virtual void gogo2(int a) { printf(" Derived :: gogo2 (int) \n"); };
   void gogo3(int a) { printf(" Derived :: gogo3 (int) \n"); };       
};

int main() {
   std::cout << "Derived" << std::endl;
   auto obj = new Derived ;
   obj->gogo(7);
   obj->gogo1(7);
   obj->gogo2(7);
   obj->gogo3(7);
   std::cout << "Base" << std::endl;
   auto base = (Base*)obj;
   base->gogo(7);
   base->gogo1(7);
   base->gogo2(7);
   base->gogo3(7);

   std::string s;
   std::cout << "press any key to exit" << std::endl;
   std::cin >> s;
   return 0;
}

output

Derived
 Derived :: gogo (int)
 Derived :: gogo1 (int)
 Derived :: gogo2 (int)
 Derived :: gogo3 (int)
Base
 Derived :: gogo (int)
 Derived :: gogo1 (int)
 Base :: gogo2 (int)
 Base :: gogo3 (int)
press any key to exit

the best way is using the base::function as say @sth

Upvotes: 0

AlwaysTraining
AlwaysTraining

Reputation: 2179

Sometimes you need to call the base class' implementation, when you aren't in the derived function...It still works:

struct Base
{
    virtual int Foo()
    {
        return -1;
    }
};

struct Derived : public Base
{
    virtual int Foo()
    {
        return -2;
    }
};

int main(int argc, char* argv[])
{
    Base *x = new Derived;

    ASSERT(-2 == x->Foo());

    //syntax is trippy but it works
    ASSERT(-1 == x->Base::Foo());

    return 0;
}

Upvotes: 87

Tunvir Rahman Tusher
Tunvir Rahman Tusher

Reputation: 6641

If you want to call a function of base class from its derived class you can simply call inside the overridden function with mentioning base class name(like Foo::printStuff()).

code goes here

#include <iostream>
using namespace std;

class Foo
{
public:
    int x;

    virtual void printStuff()
    {
         cout<<"Base Foo printStuff called"<<endl;
    }
};

class Bar : public Foo
{
public:
    int y;

    void printStuff()
    {
        cout<<"derived Bar printStuff called"<<endl;
        Foo::printStuff();/////also called the base class method
    }
};

int main()
{
    Bar *b=new Bar;
    b->printStuff();
}

Again you can determine at runtime which function to call using the object of that class(derived or base).But this requires your function at base class must be marked as virtual.

code below

#include <iostream>
using namespace std;

class Foo
{
public:
    int x;

    virtual void printStuff()
    {
         cout<<"Base Foo printStuff called"<<endl;
    }
};

class Bar : public Foo
{
public:
    int y;

    void printStuff()
    {
        cout<<"derived Bar printStuff called"<<endl;
    }
};

int main()
{

    Foo *foo=new Foo;
    foo->printStuff();/////this call the base function
    foo=new Bar;
    foo->printStuff();
}

Upvotes: 6

MartinStettner
MartinStettner

Reputation: 29174

Just in case you do this for a lot of functions in your class:

class Foo {
public:
  virtual void f1() {
    // ...
  }
  virtual void f2() {
    // ...
  }
  //...
};

class Bar : public Foo {
private:
  typedef Foo super;
public:
  void f1() {
    super::f1();
  }
};

This might save a bit of writing if you want to rename Foo.

Upvotes: 29

Alex B
Alex B

Reputation: 84972

Yes,

class Bar : public Foo
{
    ...

    void printStuff()
    {
        Foo::printStuff();
    }
};

It is the same as super in Java, except it allows calling implementations from different bases when you have multiple inheritance.

class Foo {
public:
    virtual void foo() {
        ...
    }
};

class Baz {
public:
    virtual void foo() {
        ...
    }
};

class Bar : public Foo, public Baz {
public:
    virtual void foo() {
        // Choose one, or even call both if you need to.
        Foo::foo();
        Baz::foo();
    }
};

Upvotes: 143

Related Questions