2012-11-04 52 views
8

这是我正在尝试的。 MinGW g ++ 4.7.0。C++ 11初始化类静态常量数组

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

我尝试编译,并得到下面的输出:

>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应该允许这样的类初始化静态常量数组?还是必须像C++ 11之前一样在类之外定义它?

回答

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]

编译器告诉缺什么:

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'

为了使连接器快乐,你必须在源文件中的某个地方加入这一行(不是头文件):

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

嘿,我有同样的问题,但我想知道为什么连接器需要这一行? C++ 11是否已经在类定义中支持init成员? – liuyanghejerry

+2

@liuyanghejerry这里有两件独立的事情。首先是初始化,并且自从C++ 03开始,它就被允许在整数类型的头文件中。正如你所看到的,只要它们是constexpr,这个C++特性在C++ 11中被扩展用于其他类型。另一件事是为这个const成员记忆一个房间。如果你拿这样的变量的地址('&Fruit :: VALUES [1]'),它必须存在于某处。这个“某处”就是源文件中的这个定义。 – PiotrNycz

+0

@liuyanghejerry我不确定这是否被C++ std所允许,但是在gcc中,只要您不以任何方式使用此变量的地址,您可以跳过源代码文件中的这个定义 - 但这并不容易 - 任何函数const引用强制编译器查找const变量定义。 – PiotrNycz