Modifica della modalità di accesso alla funzione nella class derivata

Considera il seguente frammento:

struct Base { virtual ~Base() {} virtual void Foo() const = 0; // Public }; class Child : public Base { virtual void Foo() const {} // Private }; int main() { Child child; child.Foo(); // Won't work. Foo is private in this context. static_cast (child).Foo(); // Okay. Foo is public in this context. } 

È questo C ++ legale? “Questo” sta cambiando la modalità di accesso della funzione virtuale nella class derivata.

Sì, la modifica della modalità di accesso nelle classi derivate è legale.

Questo è simile nella forma ma diverso nell’intenzione per l’idioma dell’interfaccia non virtuale . Alcune motivazioni sono qui fornite:

Il punto è che esistono funzioni virtuali per consentire la personalizzazione; a meno che non debbano essere invocati direttamente dal codice delle classi derivate, non è necessario renderli mai privati.

Per quanto riguarda il motivo per cui si dovrebbe effettivamente rendere public qualcosa in base ma private in derivato senza eredità private o protected è oltre me.

Questo è legale C ++, §11.6 / 1 dice:

L’accesso viene verificato nel punto di chiamata utilizzando il tipo dell’espressione utilizzata per indicare l’object per il quale viene chiamata la funzione membro (B * nell’esempio sopra). In generale, l’accesso della funzione membro nella class in cui è stato definito (D nell’esempio precedente) non è noto.

Come hai notato, Child::Foo() è quindi ancora accessibile tramite la class base, che nella maggior parte dei casi è indesiderata:

  Child* c = new Child; Base* b = c; c->Foo(); // doesn't work, Child::Foo() is private b->Foo(); // works, calls Child::Foo() 

Fondamentalmente, la dichiarazione a cui fai riferimento nell’espressione determina la modalità di accesso, ma le funzioni virtuali minano che come un’altra funzione possa effettivamente essere invocata quella nominata.

È perfettamente legale C ++. Stai semplicemente definendo un nuovo metodo nella class Child.

Ora fa ciò che vuoi che faccia, questa è un’altra domanda. Credo che la modalità di accesso non faccia parte della firma del metodo, il che significa che chiamare il metodo virtuale di Base Foo alla fine chiama il metodo Child’s Foo.

Quindi, ecco la conclusione: è legale c ++ e funziona come ti aspetteresti.

Non sto prendendo in considerazione la linea child.Foo(); che non può funzionare perché non c’è dubbio che stia tentando di accedere al metodo Foo () privato di Child.

Sembra compilare e chiamare il metodo giusto.

Ricorda che gli specificatori di accesso sono lì per aiutare un programmatore disciplinato, non per prevenire tutti i tentativi di aggirarlo a tutti i costi.

In questo caso particolare, Child non ha attività che rendono privata la funzione virtuale sovrascritta: non è prevista l’implementazione dell’interfaccia pubblica di Base, quindi la relazione “is-a” è valida? (Se non hai utilizzato l’ereditarietà pubblica, il che significa “Il bambino è una base”, il tuo trucco non funzionerebbe).