2012-11-04 28 views
8

Oto, co próbuję. MinGW g ++ 4.7.0.C++ 11 Inicjowanie klasy tablicy stałej statycznej

#include <iostream> 
#include <string> 

class Fruit 
{ 
public: 
    enum Value { APPLE, ORANGE, BANANA, NONE }; 
    static const Value VALUES[4] = { APPLE, ORANGE, BANANA, NONE }; 
    Fruit (Value v = NONE) : v_(v) { }; 
    std::string to_string() const { 
     switch (v_) { 
      case APPLE: return "apple"; 
      case ORANGE: return "orange"; 
      case BANANA: return "banana"; 
      default: return "none"; 
     } 
    } 
private: 
    Value v_; 
}; 

int main (int argc, char * argv[]) 
{ 
    for (Fruit f : Fruit::VALUES) 
     std::cout << f.to_string() << std::endl; 
    return 0; 
} 

próbuję kompilowanie go i uzyskać poniżej wynik:

>g++ -std=c++0x test.cpp 
test.cpp:9:66: error: 'constexpr' needed for in-class initialization of static d 
ata member 'const Fruit::Value Fruit::VALUES [4]' of non-integral type [-fpermis 
sive] 


>g++ -std=c++0x -fpermissive test.cpp 
test.cpp:9:66: warning: 'constexpr' needed for in-class initialization of static 
data member 'const Fruit::Value Fruit::VALUES [4]' of non-integral type [-fperm 
issive] 
cc1l4Xgi.o:test.cpp:(.text+0x1a): undefined reference to `Fruit::VALUES' 
collect2.exe: error: ld returned 1 exit status 

Czy C++ 11 powinna umożliwić inicjowanie statyczną tablicę const w klasie jak to? Czy też musi być zdefiniowana poza klasą, tak jak przed C++ 11?

Odpowiedz

17

test.cpp:9:66: error: 'constexpr' needed for in-class initialization of static d ata member 'const Fruit::Value Fruit::VALUES [4]' of non-integral type [-fpermis sive]

Compiler powiedział, czego brakuje:

class Fruit 
{ 
public: 
    enum Value { APPLE, ORANGE, BANANA, NONE }; 
    static constexpr Value VALUES[4] = { APPLE, ORANGE, BANANA, NONE }; 
    //  ^^^^^^^^^ 
... 
}; 

cc1l4Xgi.o:test.cpp:(.text+0x1a): undefined reference to `Fruit::VALUES'

Aby łącznik szczęśliwy, należy dodać tę linię gdzieś w plikach źródłowych (nie nagłówek pliku):

constexpr Fruit::Value Fruit::VALUES[4]; 
+0

Hej, mam to samo pytanie, ale zastanawiam się, dlaczego linkery potrzebują tej linii? Czy C++ 11 nie obsługuje już członków init w definicji klasy? – liuyanghejerry

+2

@liuyanghejerry Oto dwie oddzielne rzeczy tutaj. Pierwsza to inicjalizacja i jest dozwolona w nagłówku dla typów całkowitych od C++ 03. Jak widać, ta funkcja C++ została rozszerzona w C++ 11 dla innych typów, o ile są one constexpr. Drugą rzeczą jest miejsce w pamięci dla tych członków const. Jeśli weźmiesz adres takiej odmiany ('& Fruit :: VALUES [1]') to musi gdzieś istnieć. To "gdzieś" jest właśnie tą definicją w pliku źródłowym. – PiotrNycz

+0

@liuyanghejerry Nie jestem pewien, czy jest to dozwolone przez C++ std, ale w gcc możesz pominąć tę definicję w pliku źródłowym, o ile nie używasz w żaden sposób adresu tej zmiennej - ale to nie jest łatwe - każda funkcja const referencyjny wymusza kompilator, aby wyszukać definicję stałej stałej. – PiotrNycz

Powiązane problemy