2014-06-27 22 views
5

mój prosty kod wygląda następująco:Zewnętrzne funkcja klasy

a.cpp:

#include <iostream> 

namespace asd 
{ 
    class B 
    { 
    public: 
     void ss() 
     { 
      extern int i; 
      std::cout << i; 
     } 
    }; 
} 

int main() 
{ 
    asd::B e; 
    e.ss(); 
} 

b.cpp:

int i = 4; 

Czy to dobry kod z norma czy nie? Visual Studio kompiluje bez błędów, ale kompilator C++ Intel mówi: (? I @ asd @@ 3ha) nierozwiązane zewnętrznych symbolu "int asd :: I"

uzyskać więcej zabawy, jeśli zmienię b.cpp do:

namespace asd 
{ 
    int i = 4; 
} 

Następnie Visual Studio C++ 2013 mówi: nierozwiązane zewnętrznych symbolu "int i" (? ja @@ 3HA)

Ale Intel C++ kompilator mówi ok :) Jaka jest właściwa wersja tego kodu Jeśli chcę mieć tego extern w funkcji członka klasy (czy to jest legalne?)?

Edit: najlepsze wyniki, gdy zmieniamy b.cpp do:

Visual C++ drukuje 5 Intel kompilatora 4 :)

+1

Co to jest ten tajemniczy "inny kompilator"? –

+0

Porównałem wyniki z kompilatorem intel. Gcc nie testowałem. – AdamF

+0

Proszę pokazać swoje B.cpp, to kompiluje się z gcc dla mnie. – quantdev

Odpowiedz

3

Jest legalne zadeklarować lub zmienną externstatic wewnątrz dowolnej funkcji. Twoja poprawka b.cpp, w której umieścisz przestrzeń nazw wokół definicji tego extern, jest odpowiednią poprawką.

Visual Studio C++ 2013 narzeka na nazwę spoza obszaru nazw asd (sprawdź, czy te dodatkowe znaki o nazwie i reprezentują). Jest to niepoprawne, ponieważ deklaracja umieszcza i w przestrzeni nazw asd.

Standard C++ ilustruje to w punkcie 3.5.7. Używa on jako przykładu funkcji extern, ale ilustruje zasadę umieszczania nazwy w otaczającym obszarze nazw.

namespace X { 
    void p() { 
     q(); // error: q not yet declared 
     extern void q(); // q is a member of namespace X 
    } 
    void middle() { 
     q(); // error: q not yet declared 
    } 
    void q() { /* ... */ } // definition of X::q 
} 
void q() { /* ... */ } // some other, unrelated q 

Uwagi na liniach 4, 9 i 11 pokazują, że nazwa zadeklarowana z extern wewnątrz funkcji użytkownik musi być umieszczone w przestrzeni nazw okalającego. Jest to dobry, samodzielny test testowy ilustrujący błąd w kompilatorze Microsoftu.

2

Wygląda Visual Studio jest źle.

To co znalazłem w projekcie standardu:

3.3.2/10

deklaracje funkcji w zakresie bloku i deklaracji zmiennych ze specyfikacją w zakresie bloku extern odnoszą się do deklaracji, które są członkami otaczającej przestrzeni nazw, ale nie wprowadzają nowych nazw do tego zakresu.

Powiedziawszy to, chciałbym przenieść oświadczenie extern z funkcji i do przestrzeni nazw, aby zobaczyć, czy to robi jakąkolwiek różnicę.

namespace asd 
{ 
    extern int i; 
    class B 
    { 
    public: 
     void ss() 
     { 
      std::cout << i; 
     } 
    }; 
}