2009-10-14 10 views
8

Il seguente codice è legale C++ o no?Dichiarare ma non definire struct/class inner - legal C++ o no?

class Foo 
{ 
    class Bar; 

    void HaveADrink(Bar &bar); 
    void PayForDrinks(Bar &bar); 

    public: 
    void VisitABar(int drinks); 
}; 

class Foo::Bar 
{ 
    public: 
    int countDrinks; 
}; 

void Foo::HaveADrink(Bar &bar) 
{ 
    bar.countDrinks++; 
} 
void Foo::PayForDrinks(Bar &bar) 
{ 
    bar.countDrinks = 0; 
} 
void Foo::VisitABar(int drinks) 
{ 
    Bar bar; 
    for (int i=0; i<drinks; i++) HaveADrink(bar); 
    PayForDrinks(bar); 
} 

Sia Visual C++ e GCC accetta, ma il codice sembra un po 'strano per me e mi dispiacerebbe averlo rifiutato da qualche futuro compilatore.

Tuttavia, il modello mi sembra utile per ridurre le dipendenze del tempo di compilazione - lo uso spesso per dichiarare le strutture che sono utilizzate per passare un "contesto" (un gruppo di variabili) che sono condivise tra alcune funzioni che risiedono tutte nello stesso file cpp, e in questo modo non devo introdurre la definizione di "contesto" nell'interfaccia pubblica.

+0

Sono appena in procinto di creare un paio di classi di contesto, quindi sono anch'io interessato. A proposito, rendere countDrinks accessibili al pubblico. – stefaanv

+0

Ho ragione ad assumere che ti riferisci alla definizione di 'classe Foo :: Bar'? – MSalters

risposta

10

legale, e anzi utile per nascondere i dettagli di implementazione al mondo esterno.

9

[modifica] Originariamente ho detto che questo era il "Pimpl": http://c2.com/cgi/wiki?PimplIdiom ma sono d'accordo che questo è solo una parte di Pimpl è di circa. Questa tecnica è usata da Pimpl.

Stai "inoltrando" la classe Bar all'interno della classe Foo. Perfettamente legale finché non si fa nulla all'interno del definigino di Foo che richiederebbe la dimensione di Bar. È possibile fare riferimento a Barra utilizzando il puntatore o il riferimento (Barra * o Barra &), ma se si dichiara un membro dati in Foo come questo:

privato: Bar _bar;

Non funzionerebbe. Il motivo è perché la definizione di Foo deve essere sufficiente per determinare la dimensione di Foo. Poiché la dimensione di Bar è sconosciuta all'interno della definizione di Foo, renderebbe indeterminata la dimensione di Foo. Ma utilizzando un puntatore funzionerebbe:

privato: Bar * _bar;

Poiché la dimensione del puntatore è la stessa, e quindi nota, indipendentemente da come la barra verrà definita in seguito.

+2

Beh, non è esattamente _ l'idioma pimpl (non c'è un pimpl nel suo codice), ma hai ragione - in sostanza lo è. +1 – sbi

+1

Si riferisce solo al pimpl, dal momento che si tratta più dell'ambito di un contesto, in cui il pimpl è l'implementazione completa della classe. Ma hai ragione: puoi dichiarare un puntatore solo quando lo fai. Fatti un favore e usa il puntatore intelligente appropriato. – stefaanv

+0

Non è sicuramente PIMPL. Non c'è implementazione in Bar. –