2009-03-23 8 views
262

Sagen, ich habe Klassen Foo und Bar wie folgt aufgebaut:Kann ich die virtuelle Funktion einer Basisklasse aufrufen, wenn ich sie außer Kraft setze?

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 kommentierte, würde Ich mag die Basisklasse Funktion in der Lage sein zu nennen, die ich überschreiben bin. In Java gibt es die super.funcname() Syntax. Ist das in C++ möglich?

+1

möglich Duplikat von [virtuellen Funktionsaufruf von der Basisklasse] (http://stackoverflow.com/questions/397404/virtual-function-call-from-base-class) –

+1

Für Googler: beachten Sie, dass Sie Probleme haben mögen Ich habe es als eine Klassenmitgliedsvariable gespeichert, die kein Zeiger ist. Siehe meine Antwort hier: http: // stackoverflow.com/questions/4798966/c-Aufruf-komplett-falsch-virtuelle-Methode-eines-Objekts/42429076 # 42429076 Ich beteiligt neue/löschen, um zu beheben. – Andrew

Antwort

354

Die C++ Syntax ist wie folgt:

class Bar : public Foo { 
    // ... 

    void printStuff() { 
    Foo::printStuff(); // calls base class' function 
    } 
}; 
+8

Gibt es irgendwelche Probleme damit? Ist es eine schlechte Übung? –

+29

@David: Nein, das ist völlig normal, obwohl es von deiner Klasse abhängen könnte, wenn es wirklich nützlich ist. Rufen Sie die Basisklassenmethode nur auf, wenn etwas geschieht, was Sie wollen;). – sth

+11

Es funktioniert auch mit nicht virtuellen Basisklassenmethoden. – John

99

Ja,

class Bar : public Foo 
{ 
    ... 

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

Es ist die gleiche wie super in Java, es sei denn es ruft Implementierungen von verschiedenen Basen ermöglicht, wenn Sie mehrfache Vererbung 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(); 
    } 
}; 
+6

Dies ist eine bessere Antwort als die ausgewählte. Vielen Dank. –

26

Gerade falls Sie tun dies für viele Funktionen in der Klasse:

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

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

Dieses ein wenig Schreiben speichern könnte wenn du Foo umbenennen willst.

+1

Fun Weg, es zu tun, aber nicht mit Mehrfachvererbung funktionieren –

+0

'typedef Foo42 x5metasuper;' – Zyl

+2

Und was ist, wenn Sie mehr als 1 Basisklasse haben? Wie auch immer, es ist albern und Es ist oft sinnlos, C++ so zu verändern, dass es wie eine andere Sprache aussieht. Denken Sie nur an den Namen der Basis und nennen Sie ihn dabei. –

61

Manchmal müssen Sie die Basisklasse Implementierung 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; 
} 
6

Wenn Sie von einer Funktion der Basisklasse aufrufen wollen ihre abgeleitete Klasse können Sie einfach innerhalb der überschriebenen Funktion mit der Erwähnung des Basisklassennamens aufrufen (wie Foo :: printStuff()).

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

Auch hier kann man zur Laufzeit bestimmen, die das Objekt dieser Klasse mit der Funktion aufrufen (abgeleitet oder Base) .Aber dies erfordert Ihre Funktion in der Basisklasse muss als virtuelle markiert werden.

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

Kontrolle dieses ...

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

Ausgang

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, um die Basis verwendet :: function als @sth

sagen
0

Ja, Sie können es nennen. C++ Syntax für Elternklasse Funktion in der Kinderklasse Aufruf ist

class child: public parent { 
    // ... 

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

Lesen Sie mehr über Funktion overriding.