Domanda

La mia comprensione di base è che non c'è l'implementazione di una funzione virtuale pura, tuttavia, mi è stato detto che ci potrebbe essere l'implementazione di funzione virtuale pura.

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

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

È il codice di cui sopra OK?

Qual è lo scopo di rendere una funzione virtuale pura con un'implementazione?

È stato utile?

Soluzione

Una funzione virtual puro deve essere attuata in un tipo derivato che verrà istanziata direttamente, tuttavia il tipo di base può ancora definire un'implementazione. Una classe derivata può chiamare in modo esplicito l'implementazione della classe base (se permessi di accesso lo consentono) utilizzando un nome completo con ambito (chiamando A::f() nel tuo esempio - se A::f() erano public o protected). Qualcosa di simile:

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

};

Il caso d'uso posso pensare di fuori della parte superiore della mia testa è quando c'è un comportamento di default più o meno ragionevole, ma il progettista della classe vuole che il comportamento specie-di-default essere invocata solo in modo esplicito. Può anche essere il caso ciò che si vuole classi derivate di eseguire sempre il proprio lavoro, ma anche essere in grado di chiamare un insieme comune di funzionalità.

Si noti che anche se è consentita dal linguaggio, non è qualcosa che vedo comunemente usato (e il fatto che si può fare sembra sorprendere la maggior parte dei programmatori C ++, anche quelli più esperti).

Altri suggerimenti

Per essere chiari, si sta equivoco ciò = 0; dopo una funzione virtuale significa.

= 0 significa classi derivate devono fornire un'implementazione, non che la classe base non può fornire un'implementazione.

In pratica, quando si contrassegna una funzione virtuale pura (= 0), non v'è molto poco senso nel fornire una definizione, perché non potrà mai essere chiamato a meno che qualcuno lo fa esplicitamente così via Base :: Funzione (...) o se il costruttore della classe base chiama la funzione virtuale in questione.

Il vantaggio di questo è che costringe derivato tipi di ignorare ancora il metodo, ma fornisce anche un predefinito o additivo attuazione.

Se si dispone di codice che deve essere eseguito dalla classe derivante, ma non si vuole che sia eseguito direttamente - e si vuole costringerlo a essere sovrascritto.

Il codice è corretto, anche se tutto sommato questa non è una caratteristica spesso usato, e di solito visto solo quando si cerca di definire un distruttore virtuale pura - in questo caso si deve fornire un'implementazione . La cosa divertente è che una volta che si deriva da quella classe non è necessario eseguire l'override del distruttore.

Quindi quello uso sensibile delle funzioni virtuali pure è specificare un distruttore virtuale pura come parola chiave "non-finale".

Il seguente codice è sorprendentemente corretta:

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

Base::~Base() {}

class Derived : public Base {};

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

Dovreste dare un corpo a un distruttore virtuale pura, ad esempio:)

Leggi: http://cplusplus.co.il/ 2009/08/22 / pure-virtual-distruttore /

(link errato, archivio uso)

Sì, questo è corretto. Nel tuo esempio, le classi che derivano da un ereditano sia il F di interfaccia () e un'implementazione di default. Ma si forza classi derivate per implementare il metodo f () (anche se è solo per chiamare l'implementazione di default fornito da A).

Scott Meyers discute questo in Effective C ++ (2a edizione) Articolo # 36 Distinguere tra l'eredità di interfaccia e l'ereditarietà di implementazione. Il numero della voce potrebbe essere cambiato nell'ultima edizione.

Funzioni virtuali Pure con o senza un corpo significa semplicemente che i tipi derivati devono fornire loro attuazione.

Funzione virtuale pura corpi nella classe base sono utili se il vostro classi derivate vuole chiamare la propria implementazione della classe base.

Il 'foo virtual void () = 0;' sintassi non significa che non è possibile implementare foo () nella classe di corrente, è possibile. E ', inoltre, non significa che si deve attuarlo nelle classi derivate . Prima che mi schiaffo, osserviamo il diamante Problema: (Codice implicito, ti dispiacerebbe).

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

Ora, la obj-> foo () invocazione si tradurrà in B :: foo () e poi C :: bar ().

Si vede ... metodi virtuali puri non devono essere attuati nelle classi derivate (foo () non ha alcuna implementazione in classe C - compilatore compilerà) In C ++ ci sono un sacco di scappatoie.

La speranza ho potuto fare a: -)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top