2012-11-04 10 views
8

Hier ist, was ich versuche. MinGW g ++ 4.7.0.C++ 11 Initialisierung der Klasse statische const Array

#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; 
} 

ich es versuchen, die Zusammenstellung und die Ausgabe unten erhalten:

>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 

C++ 11 soll wie folgt eine statische const Array in einer Klasse ermöglichen Initialisierung? Oder muss es außerhalb der Klasse wie vor C++ 11 definiert werden?

Antwort

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 gesagt, was fehlt:

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'

Um Linker glücklich, diese Zeile irgendwo in Quelldateien hinzufügen müssen (nicht Datei-Header):

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

Hey, ich habe die gleiche Frage, aber ich frage mich, warum Linker diese Zeile brauchen? Unterstützt C++ 11 nicht bereits Init-Member in der Klassendefinition? – liuyanghejerry

+2

@liuyanghejerry Dies sind zwei verschiedene Dinge hier. Die erste ist die Initialisierung und sie ist seit C++ 03 im Header für Integer-Typen erlaubt. Und wie Sie sehen können, wurde diese C++ - Funktion in C++ 11 für andere Typen erweitert, solange sie conexpr sind. Die andere Sache ist ein Raum in Erinnerung für diese const Mitglieder. Wenn du eine Adresse von solchen Variablen nimmst ('& Fruit :: VALUES [1]') muss sie irgendwo existieren. Dieses "irgendwo" ist nur diese Definition in der Quelldatei. – PiotrNycz

+0

@liuyanghejerry Ich bin mir nicht sicher, ob dies von C++ std erlaubt ist, aber in gcc können Sie diese Definition in der Quelldatei überspringen, solange Sie die Adresse dieser Variablen nicht verwenden - aber das ist nicht einfach - irgendeine Funktion const referenz erzwingt den Compiler, nach der const-Variablendefinition zu suchen. – PiotrNycz