2009-08-21 21 views
6
struct A { 
    static const int a = 5; 

    struct B { 
     static const int b = a; 
    }; 

}; 

int main() { 
    return A::B::b; 
} 

Il codice sopra riportato viene compilato. Tuttavia, se si utilizza il libro Effective C++ di Scott Myers (pg 14); Abbiamo bisogno di una definizione per a oltre alla dichiarazione. Qualcuno può spiegare perché questa è un'eccezione?utilizzando un const const statico in una struct/class

+1

Il codice _aggiunge_ contiene una definizione per 'a'. –

+2

No, non contiene una definizione. –

+1

@Henk. Non proprio. Prova a passare l'indirizzo di 'a' o 'b' a una funzione e vedi quale messaggio genera il compilatore! –

risposta

18

I compilatori C++ consentono ai cost const interi (e solo agli interi) di specificare il loro valore nella posizione in cui sono dichiarati. Questo perché la variabile non è essenzialmente necessaria e vive solo nel codice (in genere è compilata).

Altri tipi di variabili (come il const char statico *) non possono in genere essere definiti nel punto in cui sono dichiarati e richiedono una definizione separata.

Per una spiegazione un po 'più precisa, rendersi conto che l'accesso a una variabile globale richiede in genere la creazione di un riferimento di indirizzo nel codice di livello inferiore. Ma la tua variabile globale è un numero intero la cui dimensione è tipicamente intorno alle dimensioni di un indirizzo, e il compilatore si rende conto che non cambierà mai, quindi perché preoccuparsi di aggiungere l'astrazione del puntatore?

+0

+1, bella risposta. Ma cosa succede se 'const' numeri interi? Possiamo specificare il loro valore in classe? – Alcott

+0

non "interi", solo un'espressione costante – czxyl

18

Con regole veramente pedanti, sì, il codice richiede una definizione per quel numero intero statico. Ma con regole pratiche e ciò che tutti i compilatori implementano perché è così che sono intese le regole di C++ 03 - no, non è necessaria una definizione.

Le regole per tali numeri interi costanti statici consentono di omettere la definizione se il numero intero viene utilizzato solo in situazioni in cui un valore viene letto immediatamente e se il membro statico può essere utilizzato in espressioni costanti.

Nella dichiarazione di reso, il valore del membro viene immediatamente letto, quindi è possibile omettere la definizione del membro intero costante statico, se questo è l'unico uso di esso. Tuttavia, la seguente situazione richiede una definizione:

struct A { 
    static const int a = 5; 

    struct B { 
     static const int b = a; 
    }; 

}; 

int main() { 
    int *p = &A::B::b; 
} 

Nessun valore viene letto qui - ma viene preso l'indirizzo. Pertanto, lo scopo dello standard C++ 03 è che devi fornire una definizione per il membro come il seguente in alcuni file di implementazione.

const int A::B::b; 

Nota che i effettivi regole che appaiono in C++ 03 standard dice che una definizione non è richiesto solo quando viene utilizzata la variabile in cui un'espressione costante è necessaria . Questa regola, tuttavia, se applicata rigorosamente, è troppo severa. Ti permetterebbe solo di omettere una definizione per situazioni come le dimensioni dell'array - ma richiederebbe una definizione in casi come un'istruzione return. Il rapporto del difetto corrispondente è here.

La dicitura di C++ 0x è stata aggiornata per includere la risoluzione del rapporto di errore e per consentire il codice come scritto.

+0

Significa che Walt W è sbagliato quando dice: "I compilatori C++ consentono di definire interi cost const (e solo interi) nella posizione in cui sono dichiarati"? Pensavo che lui fosse "stat const const a = 5;" la dichiarazione era sia dichiarazione che definizione. Se capisco correttamente, è solo una dichiarazione senza alcuna definizione e l'A :: a può essere usato solo in casi molto specifici. Sono intesrested nell'ultima parola ... – neuro

+0

Sì, anche lui ha torto. Questa è solo una dichiarazione - non è una definizione. Se ci si riferisce ad esso in casi che non leggono immediatamente un valore, è necessaria una definizione. Sembra che tu abbia ragione nel tuo commento. –

+0

Meglio? Suppongo che non fosse l'uso tecnico della "definizione" –

0

In generale, la maggior parte (e recenti) compilatori C++ consentono int const statici

È solo fortunato, forse no. Prova il compilatore più vecchio, come ad esempio gcc 2.0, e ti punirà con veemenza con un messaggio di errore meno che carino.

1

Tuttavia, se si tenta l'operando ternario senza "definire" const statici, si ottiene un errore di linker in GCC 4x:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13795

Così, anche se costrutti come int k = A::CONSTVAL; sono illegali nello standard corrente, sono supportati. Ma l'operando ternario no. Alcuni operatori sono più uguali di altri, se si ottiene la mia deriva :)

Così tanto per le regole "lax". Ti suggerisco di scrivere codice conforme allo standard se non vuoi sorprese.

Problemi correlati