2012-03-19 14 views
16

Posso capire che potrebbe esserci un motivo per dichiarare una funzione virtuale implementata (al contrario di pura) privata o protetta. Afaik, se dichiari un metodo virtuale implementato come protetto, la tua classe figlia può chiamare il metodo della classe base (e nessun altro può farlo). Se lo dichiari privato, solo la classe base può chiamare l'implementazione predefinita del metodo virtuale.C'è qualche differenza tra una funzione virtuale pura protetta e privata?

Tuttavia, con i virtuali puri, non esiste un'implementazione di base ... Quindi non è funzionalmente equivalente dichiarare un puro virtuale come privato o protetto? Un virtual puro protetto non ha senso perché non puoi mai invocare il metodo corrispondente della classe base. Ci sono degli scenari in cui un virtual puro protetto ha senso?

Ci sono alcuni argomenti simili su SO, ma non sono riuscito a trovare nulla che rispondesse concisamente alla mia domanda.

+0

È possibile implementare 'amico' per le interfacce. – Matthew

+6

Il metodo virtuale puro può avere un corpo e può essere richiamato esplicitamente come base :: pippo(). – iammilind

risposta

8

Esistono scenari in cui un virtual puro protetto produce un senso di ?

Penso che tu intenda privato qui (invece che protetto), ma penso di capire il tuo punto. In effetti, il tipo di accesso di un puro virtuale può essere sovrascritto nelle classi derivate. Ecco un esempio che potrebbe aiutare a vedere la differenza tra un privato e protetto puro virtuale:

class Parent 
{ 
    protected: virtual void foo() = 0; 
    private: virtual void bar() = 0; 
    public:   void test() { foo(); bar(); } 
}; 

class Child : public Parent 
{ 
    public: void test2() { foo(); /* bar(); // cannot be called here */ } 
}; 

class GrandChild : public Child 
{ 
    // access types here can be anything for this example 
    public: void foo() { cout << "foo" << endl; } 
    public: void bar() { cout << "bar" << endl; } 
}; 
+0

Grazie per l'esempio. Giusto per chiarire: un privato puro virtuale non può mai essere chiamato da nessuno dei suoi discendenti (ma può essere implementato da loro, quindi la classe base può invocare il metodo del suo discendente?) – Prismatic

+0

No. In questo esempio, se GrandChild ha chiamato 'foo () "all'interno di un altro dei suoi metodi, si compilerebbe e funzionerebbe come previsto, sarebbe chiamato" GrandChild :: foo ". – mfontanini

+2

Sì Pris, una funzione virtuale può essere sostituita con un tipo di accesso diverso che potrebbe aprirne l'accessibilità. – LiquidAsh

4

Prima funzione virtuale pura può essere implementato!

#include <iostream> 

class Animal 
{ 
public: 
    void eat(void); 
protected: 
    virtual void doEat(void)=0; 
}; 
void Animal::eat(void) 
{ 
    doEat(); 
} 
void Animal::doEat(void) 
{ 
    std::cout << "animal" << std::endl; 
} 

class Tiger : public Animal 
{ 
private: 
    virtual void doEat(void) 
    { 
    Animal::doEat();//here is the difference between protected and private 
    std::cout << "tiger" << std::endl; 
    } 
}; 

int main(void) 
{ 
    Animal *p = new Tiger(); 
    p->eat(); 
    return 0; 
} 

In secondo luogo, Herb Sutter ha spiegato quando utilizzare "virtuale privata" o "virtuale protetto", si può leggere da questo article .I pensare questo spiega il motivo per cui facciamo questo, non solo possiamo L'articolo dice:" Preferisci rendere private le funzioni virtuali, solo se le classi derivate devono invocare l'implementazione di base di una funzione virtuale, rendere protetta la funzione virtuale ", la tua domanda riguarda la pura funzione virtuale, non sono abbastanza sicuro se soddisfare questo principio.