¿Puedo llamar a la función virtual de una clase base si la anulo?

Resuelto Alex asked hace 15 años • 8 respuestas

Digamos que tengo clases Fooy Barlas configuro así:

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;
    }
};

Como se indica en el código, me gustaría poder llamar a la función de la clase base que estoy anulando. En Java está la super.funcname()sintaxis. ¿Es esto posible en C++?

Alex avatar Mar 23 '09 13:03 Alex
Aceptado

En C++ debes nombrar explícitamente la clase base al llamar al método de clase derivada. Esto se puede hacer desde cualquier método de la clase derivada. La anulación es un caso especial del método del mismo nombre. En Java no existe herencia múltiple, por lo que puede usar super, que nombrará de forma única la clase base. La sintaxis de C++ es así:

class Bar : public Foo {
  // ...

  void printStuff() override {  // help the compiler to check
    Foo::printStuff(); // calls base class' function
  }
};
sth avatar Mar 23 '2009 06:03 sth

Sí,

class Bar : public Foo
{
    ...

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

Es lo mismo que superen Java, excepto que permite llamar a implementaciones desde diferentes bases cuando tienes herencia múltiple.

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();
    }
};
Alex B avatar Mar 23 '2009 06:03 Alex B

A veces necesitas llamar a la implementación de la clase base, cuando no estás en la función derivada... Todavía funciona:

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;
}
AlwaysTraining avatar Jun 12 '2011 01:06 AlwaysTraining

En caso de que hagas esto para muchas funciones en tu clase:

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

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

Esto podría ahorrarle un poco de escritura si desea cambiar el nombre de Foo.

MartinStettner avatar Mar 23 '2009 15:03 MartinStettner