2012-08-06 13 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() 
    { 
    } 
}; 

Jakie są przesłanki stojące za tą niekonsekwencją traktowania połączeń do funkcji powyżej ich deklaracji? Jak mogę to zrobić wewnątrz klasy, ale nie w przestrzeni nazw lub w zasięgu globalnym?Wywołanie funkcji powyżej ich deklaracji

+0

Może kompilator przechodzi wielokrotnie poprzez implementacje metody klasy wewnątrz deklaracji klasy, podczas gdy „C” kompilator przechodzi tylko raz. Może być jakimś spuścizną, ponieważ foo() jest zasadniczo funkcją C –

+0

A jaki jest wynik po usunięciu statycznego ze statycznego void foo ?? – perilbrain

+0

@Anonymous, to nic nie zmienia – SingerOfTheFall

Odpowiedz

3

Możesz zdefiniować funkcje składowe w klasie lub po deklaracji klasy lub w niektórych z nich.

dostać jakąś spójność tutaj, reguły dla klasy z określonymi funkcjami inline jest to, że wciąż musi być skompilowany jakby funkcje zostały zdefiniowane po klasy.

Kod

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

    static void bar() 
    {  } 
}; 

kompiluje takie same jak

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

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

void C::bar() 
{  } 

i teraz nie ma magii w widoczności, ponieważ wszystkie funkcje można zobaczyć wszystko zadeklarowane w klasie.

0

Cóż, może dlatego, że masz deklarację klasową w jednym miejscu, a kompilator może łatwo uzyskać informacje o jej członkach.

Z drugiej strony przestrzeń nazw może zawierać wiele różnych plików i nie można oczekiwać, że kompilator je przejrzy, ponieważ nie wie, gdzie szukać.

Aby tego uniknąć, po prostu użyj function prototypes.

0

Nie jestem pewien, ale moja myśl jest taka, że ​​class jest nieco obiekt (źle używany), gdzie wszystkie jego elementy wewnętrzne współpracować (ogólnie mówiąc), jej członek będzie na pewno trzeba jej metody.

Ale przestrzeń nazw jest inna, funkcje nie są powiązane. Oznacza to, że funkcja nie jest przeznaczona do pracy z każdą inną funkcją wewnątrz przestrzeni nazw.

Deklaracja podziału i definicje to najlepsze, co możesz zrobić.

If foo()bar() jego potrzeb najprawdopodobniej będzie w tym samym pliku deklaracji, i działa w ten sposób

1
  1. Przestrzenie nazw mogą zostać wznowione i nowe rzeczy można dodać w dowolnym miejscu. Klasy nie można otworzyć ponownie - całą ich zawartość należy umieścić w jednym miejscu.

  2. Prototypy funkcji są legalne w przestrzeniach nazw, ale nie w klasach.

Możesz napisać

namespace n 
{ 
    void foo(); 

    void bar() 
    { 
     foo(); 
    } 

    void foo() 
    { 
    } 
} 

Ale nie

class C 
{ 
    void foo(); 

    void bar() 
    { 
     foo(); 
    } 

    void foo() 
    { 
    } 
} 

Więc klas potrzebują takiej funkcji znacznie więcej i jest o wiele łatwiejsze do wdrożenia go dla nich niż dla nazw.

0

Zobacz poniższy cytat z zakresu klasy standard

3.3.7 [basic.scope.class]

1) następujące zasady opisuje zakres nazw zgłoszonych w klasach. 1) Potencjalny zakres nazw zadeklarowanych w klasie składa się nie tylko z deklaratywnego regionu po punkcie deklaracji nazwy, ale także z wszystkich ciał funkcji, domyślnych argumentów i usztywnień lub nierównomierności niestatycznych elementy danych w tej klasie (w tym takie rzeczy w klasach zagnieżdżonych).

2) Nazwa N użyta w klasie S odnosi się do tej samej deklaracji w kontekście i po ponownej ocenie w gotowego zakresu S. Nie jest wymagana diagnostyka w przypadku naruszenia tej zasady.

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 }; 
}; 
Powiązane problemy