webentwicklung-frage-antwort-db.com.de

reine virtuelle Funktion mit Implementierung

Mein grundlegendes Verständnis ist, dass es keine Implementierung für eine rein virtuelle Funktion gibt. Mir wurde jedoch mitgeteilt, dass es möglicherweise eine Implementierung für eine rein virtuelle Funktion gibt.

class A {
public:
    virtual void f() = 0;
};

void A::f() {
    cout<<"Test"<<endl;
}

Ist der Code über OK?

Was ist der Zweck, um es mit einer Implementierung zu einer rein virtuellen Funktion zu machen?

159
skydoor

Eine reine virtual -Funktion muss in einem abgeleiteten Typ implementiert werden, der direkt instanziiert wird. Der Basistyp kann jedoch weiterhin eine Implementierung definieren. Eine abgeleitete Klasse kann die Basisklassenimplementierung explizit aufrufen (sofern die Zugriffsberechtigungen dies zulassen), indem sie in Ihrem Beispiel einen vollständigen Namen verwendet (indem sie A::f() aufruft - wenn A::f()public oder protected). So etwas wie:

class B : public A {

    virtual void f() {
        // class B doesn't have anything special to do for f()
        //  so we'll call A's

        // note that A's declaration of f() would have to be public 
        //  or protected to avoid a compile time problem

        A::f();
    }

};

Der Anwendungsfall, an den ich auf Anhieb denken kann, ist, wenn es ein mehr oder weniger vernünftiges Standardverhalten gibt, der Klassendesigner jedoch möchte, dass dieses Standardverhalten nur explizit aufgerufen wird. Es kann auch der Fall sein, dass abgeleitete Klassen immer ihre eigene Arbeit ausführen sollen, aber auch in der Lage sind, einen gemeinsamen Satz von Funktionen aufzurufen.

Beachten Sie, dass dies, obwohl es von der Sprache zugelassen ist, nicht häufig verwendet wird (und die Tatsache, dass es möglich ist, scheint die meisten C++ - Programmierer zu überraschen, selbst erfahrene).

194
Michael Burr

Um klar zu sein, Sie missverstehen was = 0; nach einer virtuellen Funktion bedeutet.

= 0 bedeutet, dass abgeleitete Klassen eine Implementierung bereitstellen müssen, nicht dass die Basisklasse keine Implementierung bereitstellen kann.

In der Praxis hat es wenig Sinn, eine virtuelle Funktion als rein (= 0) zu kennzeichnen, da sie nur dann aufgerufen wird, wenn dies explizit über Base :: Function (...) erfolgt oder wenn die Der Basisklassenkonstruktor ruft die betreffende virtuelle Funktion auf.

70
Terry Mahaffey

Dies hat den Vorteil, dass abgeleitete Typen gezwungen werden, die Methode weiterhin zu überschreiben, aber auch eine Standardimplementierung oder eine additive Implementierung bereitgestellt werden.

20
JaredPar

Wenn Sie Code haben, der von der ableitenden Klasse ausgeführt werden soll, aber nicht direkt ausgeführt werden soll, und erzwingen möchten, dass er überschrieben wird.

Ihr Code ist korrekt, obwohl dies alles in allem keine häufig verwendete Funktion ist und normalerweise nur beim Versuch angezeigt wird, einen reinen virtuellen Destruktor zu definieren - in diesem Fall müssen Sie müssen eine Implementierung bereitstellen. Das Lustige ist, dass Sie, sobald Sie von dieser Klasse abgeleitet sind, den Destruktor nicht mehr überschreiben müssen.

Daher ist die einzige sinnvolle Verwendung von rein virtuellen Funktionen die Angabe eines rein virtuellen Destruktors als "nicht endgültiges" Schlüsselwort.

Der folgende Code ist überraschend richtig:

class Base {
public:
  virtual ~Base() = 0;
};

Base::~Base() {}

class Derived : public Base {};

int main() { 
  // Base b; -- compile error
  Derived d; 
}
17

Man müsste zum Beispiel einem reinen virtuellen Destruktor einen Körper geben :)

Lesen Sie: http://cplusplus.co.il/2009/08/22/pure-virtual-destructor/

(Link kaputt, Archiv benutzen)

5
rmn

Reine virtuelle Funktionen mit oder ohne Body bedeuten lediglich, dass die abgeleiteten Typen ihre eigene Implementierung bereitstellen müssen.

Reine virtuelle Funktionskörper in der Basisklasse sind nützlich, wenn Ihre abgeleiteten Klassen Ihre Basisklassenimplementierung aufrufen möchten.

4
Brian R. Bondy

Ja das ist korrekt. In Ihrem Beispiel erben von A abgeleitete Klassen sowohl die Schnittstelle f() als auch eine Standardimplementierung. Sie erzwingen jedoch, dass abgeleitete Klassen die Methode f() implementieren = (auch wenn nur die von A bereitgestellte Standardimplementierung aufgerufen werden soll).

Scott Meyers diskutiert dies in Effective C++ (2nd Edition) Item # 36 Unterscheiden Sie zwischen der Vererbung der Schnittstelle und der Vererbung der Implementierung. Die Artikelnummer hat sich möglicherweise in der letzten Ausgabe geändert.

4
Yukiko

Die 'virtuelle Leere foo () = 0;' Syntax bedeutet nicht, dass Sie foo () in der aktuellen Klasse nicht implementieren können. Das bedeutet auch nicht, dass Sie es in abgeleiteten Klassen implementieren müssen. Bevor Sie mich schlagen, lassen Sie uns das Diamant-Problem beobachten: (Impliziter Code, wohlgemerkt).

class A
{
public: 
    virtual void foo()=0;
    virtual void bar();
}

class B : public virtual A
{
public:
    void foo() { bar(); }
}

class C : public virtual A
{
public:
    void bar();
}

class D : public B, public C
{}

int main(int argc, const char* argv[])
{
    A* obj = new D();
    **obj->foo();**
    return 0;
}

Der Aufruf von obj-> foo () führt nun zu B :: foo () und dann zu C :: bar ().

Sie sehen ... rein virtuelle Methoden müssen nicht in abgeleiteten Klassen implementiert werden (foo () hat keine Implementierung in Klasse C - Compiler wird kompiliert) In C++ gibt es viele Lücken.

Hoffe ich konnte helfen :-)

2
Nir Hedvat