Domanda

Stavo cercando di capire cosa succede quando una classe derivata dichiara privata una funzione virtuale.Quello che segue è il programma che ho scritto

#include <iostream>
using namespace std;
class A
{
    public:
        virtual void func() {
        cout<<"A::func called"<<endl;
    }
    private:
};
class B:public A
{
    public:
    B()
    {
        cout<<"B constructor called"<<endl;
    }
    private:
    void func() {
        cout<<"B::func called"<<endl;
    }
};
int main()
{
    A *a = new B();
    a->func();
    return 0;
}

Sorprendentemente (per me) l'output è stato:

B constructor called
B::func called

Non si sta violando l'accesso privato impostato per quella funzione.È questo il comportamento previsto?Si tratta di una soluzione alternativa standard o di una scappatoia?I livelli di accesso vengono ignorati durante la risoluzione delle chiamate di funzione tramite VTABLE?

Qualsiasi informazione su questo comportamento sarebbe molto utile.

Inoltre è stato menzionato che la sovrascrittura privata di un membro virtuale impedirebbe ad altre classi di ereditarlo.Anche questo sta avendo problemi.Modificare il programma di cui sopra per includere:

class C: public B
{
    public:
    void func() {
        cout<<"C::func called"<<endl;
    }
};

e il programma di test principale per:

int main()
{
    A *a = new C();
    a->func();
    return 0;
}

l'uscita è:

C::func called
È stato utile?

Soluzione

Il comportamento è corretto. Ogni volta che si dichiara la funzione di "virtuale", si indica al compilatore di generare una chiamata virtuale, al posto della chiamata diretta a questa funzione. Ogni volta che si sostituisce la funzione virtuale nella classe discendente, si specifica il comportamento di questa funzione (non si cambia la modalità di accesso per i clienti, che si affidano a un'interfaccia del "padre").

La modifica della modalità di accesso per la funzione virtuale nella classe discendente significa che si desidera nascondere da quei clienti, che utilizzano la classe discendente direttamente (che si affidano a interfaccia "del bambino").

Si consideri l'esempio:

void process(const A* object) {
   object->func();
}

funzione "processo" si basa sull'interfaccia del genitore. Si prevede di lavorare per qualsiasi classe, pubblico-derivato da A. Non è possibile B pubblico-derivare da un (dicendo "ogni B è A"), ma nasconde una parte della sua interfaccia. Coloro, che si aspettano "A" deve ricevere un completamente funzionale "A".

Altri suggerimenti

Questo è un comportamento ben definito. Se a erano un B* questo non sarebbe compilare. La ragione è che l'accesso utente è risolto staticamente dal compilatore, non dinamicamente a run-time. Molti libri C ++ suggeriscono che si evita la codifica in questo modo perché confonde programmatori meno esperti.

Bene, stai chiamando A::func() che è public sebbene in a B oggetto da cui viene sovrascritto B::func().Questo è un modello comune con le seguenti implicazioni:

  • func non è destinato ad essere chiamato derivato B oggetti

  • func non può essere sovrascritto nelle classi derivate da B

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