此代码是否已损坏或是否存在g ++中的错误?

时间:2011-07-11 18:19:20

标签: c++ linker-errors

由于一些奇怪的原因,g ++(版本4.5.0和4.5.2)无法编译此代码:

bool somefunc() {
    return false;
}

class C {
  public:
    static const int a = 0;
    static const int b = 1;
};

class myclass {
  public:
    int check() {
        return somefunc() ? C::a : C::b;
        // if(somefunc()) return C::a; else return C::b;
    }
};

int main() {
    myclass obj;
    obj.check();
    return 0;
}

它给了我这个错误:

/tmp/ccyvvTUy.o:/home/mati/test.cpp:14: undefined reference to `C::a'
/tmp/ccyvvTUy.o:/home/mati/test.cpp:14: undefined reference to `C::b'
collect2: ld returned 1 exit status

如果我将有问题的行更改为注释行,它会编译得很好,这很奇怪。 我的代码和我对C ++不了解的东西是不是有问题,还是只是G ++中的一个错误?

4 个答案:

答案 0 :(得分:18)

此代码是否合法<{3}}

无论哪种方式,根据一些读数,实际的常量需要在使用前定义,而不仅仅是声明。也就是说,

class C {
  public:
    static const int a = 0;
    static const int b = 1;
};

const int C::a;
const int C::b;

或者只是使用用于容纳较旧编译器的enum hack(但这可能是唯一合法的方式):

class C {
  public:
    enum { a = 0, b = 1 };
};

答案 1 :(得分:5)

见9.4.2 / 4:

  

如果静态数据成员是const integral或const枚举   type,它在类定义中的声明可以指定一个常量   初始化器,它应是一个整数常量表达式(5.19)。在   在这种情况下,成员可以出现在整数常量表达式中   在其范围内。该成员仍应在命名空间中定义   范围,如果它在程序和命名空间范围定义中使用   不得包含初始化程序。

关于“使用”的确切含义存在一些争论(我相信),尽管我的理解大致是if程序需要变量的地址然后在此上下文中“使用”。在我看来,将三元组改为if/else或更改优化级别可能会改变程序视图(如g ++所见)从而导致失败或成功,这似乎并不合理。另请注意,如果您违反此要求,则不会对必要的诊断进行任何说明。

总是定义静态成员不会出错。

答案 2 :(得分:0)

尝试在没有优化的情况下全局定义它。

const int C::a = 0; 

答案 3 :(得分:-2)

更改以下行      return somefunc()? C :: a:C :: b;

要     return(somefunc()?C :: a:C :: b);

它应该编译。