2012-08-06 15 views
6
void foo() 
{ 
    bar();   // error: ‘bar’ has not been declared 
} 

void bar() 
{ 
} 

namespace N 
{ 
    void foo() 
    { 
     N::bar(); // error: ‘bar’ is not a member of ‘N’ 
    } 

    void bar() 
    { 
    } 
} 

class C 
{ 
    static void foo() 
    { 
     C::bar(); // works just fine 
    } 

    static void bar() 
    { 
    } 
}; 

Qual è la logica alla base di questa incoerenza nel trattare le chiamate alle funzioni al di sopra della loro dichiarazione? Come mai posso farlo all'interno di una classe, ma non all'interno di uno spazio dei nomi o nell'ambito globale?funzioni di chiamata sopra la loro dichiarazione

+0

Forse, compilatore passa più volte attraverso implementazioni di metodo di classe all'interno di dichiarazione di classe, mentre "C" compilatore passa solo una volta. Potrebbe esserci qualche retaggio, dato che foo() è essenzialmente C-function –

+0

E qual è il risultato dopo aver rimosso la static da static void foo ?? – perilbrain

+0

@Anonimo, questo non cambia nulla – SingerOfTheFall

risposta

3

È possibile definire le funzioni membro all'interno della classe o dopo la dichiarazione della classe o alcune di ciascuna.

per ottenere qualche consistenza qui, le regole per una classe con le funzioni inline definite è che deve ancora essere compilato come se le funzioni sono state definite dopo classe.

Il codice

class C { 
    static void foo() 
    { 
     C::bar(); // works just fine 
    } 

    static void bar() 
    {  } 
}; 

compila la stessa

class C { 
    static void foo(); 
    static void bar(); 
}; 

void C::foo() 
{ C::bar(); } 

void C::bar() 
{  } 

e ora non c'è magia nella visibilità, perché le funzioni possono tutti vedere tutto dichiarato nella classe.

0

Forse perché la dichiarazione della classe è presente in un unico punto e il compilatore può facilmente ottenere le informazioni dei suoi membri.

Uno spazio dei nomi, d'altra parte, può avere roba in tonnellate di file diversi, e non ci si può aspettare che il compilatore li guardi, perché non sa dove cercare in primo luogo.

Per evitare questo, utilizzare solo function prototypes.

0

non sono sicuro, ma il mio pensiero è che una class è un po 'un oggetto (male utilizzato) in cui tutti i suoi componenti interni lavorano insieme (in generale), i suoi Stati sarà sicuramente bisogno i suoi metodi.

Ma uno spazio dei nomi è diverso, le funzioni non sono correlate. Significa che una funzione non ha lo scopo di funzionare con tutte le altre funzioni all'interno del namespace.

Quindi la dichiarazione e le definizioni di suddivisione sono la cosa migliore che si possa fare.

If foo() esigenze bar() suo più probabile che sarà nello stesso file di dichiarazione, e avrebbe funzionato in questo modo

1
  1. namespace possono essere riaperti e le cose nuove possono essere aggiunte in qualsiasi luogo. Le classi non possono essere riaperte: tutto il loro contenuto deve essere inserito nel posto unico .

  2. I prototipi di funzione sono legali in domini ma non in classi.

È possibile scrivere

namespace n 
{ 
    void foo(); 

    void bar() 
    { 
     foo(); 
    } 

    void foo() 
    { 
    } 
} 

Ma non

class C 
{ 
    void foo(); 

    void bar() 
    { 
     foo(); 
    } 

    void foo() 
    { 
    } 
} 

Quindi classi bisogno di queste funzionalità molto di più ed è molto più facile da implementare per loro che per gli spazi dei nomi.

0

Vedere la citazione di seguito dall'ambito di applicazione Classe standard

3.3.7 [basic.scope.class]

1) Le seguenti regole descrivono la portata dei nomi dichiarati nelle classi. 1) Il potenziale ambito di un nome dichiarato in una classe è costituito non solo dalla regione dichiarativa che segue il punto di dichiarazione del nome, ma anche da di tutti i corpi delle funzioni, argomenti predefiniti e controventi o equalinitializzatori di tipo non statico membri di dati in quella classe (comprese cose simili in classi annidate).

2) Un nome N utilizzato in una classe S deve fare riferimento alla stessa dichiarazione nel suo contesto e quando rivalutato in l'ambito completo di S. Nessuna diagnostica è richiesta per una violazione di questa regola.

typedef int c; 
enum { i = 1 }; 

class X { 
    char v[i]; // error: i refers to ::i 
       // but when reevaluated is X::i 
    int f() { return sizeof(c); } // OK: X::c 
    char c; 
    enum { i = 2 }; 
}; 
Problemi correlati