2013-07-14 9 views
5

Il mio amico mi ha mostrato il codice follow"using" con nome classe base per modificare l'accesso valido?

struct A { 
    virtual void f() = 0; 
    virtual void g() = 0; 
}; 

struct AInternal : A { 
    virtual void f() { /* ... */ } 
    virtual void g() { /* ... */ } 
}; 

Lui sta usando AInternal come una classe interna che implementa la maggior parte (se non tutti A). Ha quindi ereditato da AInternal, ma poiché desidera che AInternal rimanga inaccessibile (dal momento che è un dettaglio di implementazione), eredita protetto (implementato in termini di). Quello che ha fatto anche stato using ing il nome della classe di base per rendere A accessibile (è stato protetto per impostazione predefinita, in quanto AInternal è stato ereditato protetto troppo)

struct C : protected AInternal { 
    using AInternal::A; 
}; 

In realtà, questo ha funzionato bene (ma come abbiamo scoperto successivamente, ancora mantenuto le funzioni membro private - solo la classe base è stata effettuata public), ma ha funzionato solo su GCC. Non riesce a rendere la base A accessibile. Qualche idea? Potremmo persino farlo per rompere il codice che funziona su Clang

struct C : public AInternal { 
protected: 
    using AInternal::A; 
}; 

C *c = 0; 
A *a = c; // error on GCC! 

Qualcuno può aiutare per favore?

+0

Se ho capito bene, A definisce l'interfaccia che deve essere fornita da C. Ciò che in realtà non capisco è l'idea alla base dell'intero setup. Rende inaccessibili i metodi pubblici in 'AInternal' se non sono presenti in' A', ma si possono avere metodi privati ​​in 'AInternal' ed ereditare pubblico in C. – Pixelchemist

+0

@Pixelchemist l'idea era di usare' AInternal :: A' make il membro funziona di nuovo pubblico. Non funzionava, ma quello che * faceva * faceva era rendere accessibile la classe base 'A'. –

+0

Sì, ma non capisco il motivo per questo tipo di layout. Perché non usare i metodi dell'interfaccia in "AInternal", utilizzare l'ereditarietà pubblica e stare bene? I "dettagli di implementazione" come le funzioni di supporto o altri membri possono ancora essere privati ​​in 'AInternal'. – Pixelchemist

risposta

5

Si sta solo influenzando la visibilità del nome della classe immessa. La protezione dell'accesso del subobject di base o dei suoi membri non dovrebbe essere influenzata. Se Clang o GCC gli permettono di influenzare la validità di un cast o l'accesso all'interno della base, questo è il loro bug.

[class.member.lookup] 10,2/3 dice

Nel set dichiarazione, utilizzando-dichiarazioni sono sostituiti dai membri designati, e dichiarazioni di tipo (compresi-classe nomi iniettati) sono sostituiti dai tipi che designano.

La classe base subobject non ha un nome nella ricerca membro; il nome della classe iniettata fa.

+0

Bene, parla del diavolo. Ho appena trovato un caso nel mio codice, dove ho erroneamente assunto che un nome-tipo-immesso avesse la stessa qualifica di accesso della classe base che l'ha introdotto. Si scopre che se si dipende veramente da esso, è meglio definire esplicitamente il proprio nome salato o utilizzare l'idioma dei tratti. – Potatoswatter

+0

Grazie! Non avevo idea di tutto ciò e ho iniziato a dormire male a causa della visibilità della classe base. +1 –

Problemi correlati