web-dev-qa-db-ger.com

Kann ich die virtuelle Funktion einer Basisklasse aufrufen, wenn ich sie überschreibe?

Angenommen, ich habe Klassen Foo und Bar wie folgt eingerichtet:

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

Wie im Code kommentiert, möchte ich die Funktion der Basisklasse aufrufen können, die ich überschreibe. In Java gibt es die Syntax super.funcname(). Ist das in C++ möglich?

299
Alex

Die C++ - Syntax sieht so aus:

class Bar : public Foo {
  // ...

  void printStuff() {
    Foo::printStuff(); // calls base class' function
  }
};
397
sth

Ja,

class Bar : public Foo
{
    ...

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

Es ist dasselbe wie super in Java, nur dass Implementierungen von verschiedenen Basen aufgerufen werden können, wenn Sie mehrere Vererbungen haben.

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();
    }
};
108
Alex B

Manchmal müssen Sie die Implementierung der Basisklasse aufrufen, wenn Sie nicht in der abgeleiteten Funktion sind ... Es funktioniert immer noch:

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

Nur für den Fall, dass Sie dies für viele Funktionen in Ihrer Klasse tun:

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

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

Dies kann etwas Schreiben sparen, wenn Sie Foo umbenennen möchten.

27
MartinStettner

Wenn Sie eine Funktion der Basisklasse aus ihrer abgeleiteten Klasse aufrufen möchten, rufen Sie einfach die überschriebene Funktion mit dem Namen der Basisklasse (wie Foo :: printStuff () ) auf.

code geht hier

#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();
}

Sie können wiederum zur Laufzeit festlegen, welche Funktion mithilfe des Objekts dieser Klasse (abgeleitete Klasse oder Basis) aufgerufen werden soll. Dazu muss Ihre Funktion in der Basisklasse jedoch als virtuell markiert sein.

code unten

#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();
}

Überprüfen Sie dies...

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

ausgabe

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

der beste Weg ist die Verwendung der base :: function wie etwa @sth

Ja, du kannst es nennen. C++ - Syntax für den Aufruf der übergeordneten Klassenfunktion in der untergeordneten Klasse ist 

class child: public parent {
  // ...

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

Lesen Sie mehr über Funktion Überschreiben .

0
Atif