2011-03-26 16 views
15

这是交易。我有一个静态类,其中包含用于获取输入的几个静态函数。该类包含一个私有静态成员变量,用于指示用户是否输入了任何信息。每种输入方法都会检查用户是否输入了任何信息,并相应地设置状态变量。我认为这将是使用三元运算符的好时机。不幸的是,我不能,因为编译器不喜欢那样。为什么静态成员变量不能和三元运算符一起使用?

我复制了这个问题,然后尽可能简化我的代码,以使它易于理解。这不是我的原始代码。

这是我的头文件:

#include <iostream> 

using namespace std; 

class Test { 
public: 
    void go(); 
private: 
    static const int GOOD = 0; 
    static const int BAD = 1; 
}; 

这里是我的实现与三元运算符:

#include "test.h" 

void Test::go() { 
    int num = 3; 
    int localStatus; 
    localStatus = (num > 2) ? GOOD : BAD; 
} 

这里的主要功能:

#include <iostream> 
#include "test.h" 

using namespace std; 

int main() { 
    Test test = Test(); 
    test.go(); 
    return 0; 
} 

当我尝试编译此,我得到这个错误信息:

test.o: In function `Test::go()': 
test.cpp:(.text+0x17): undefined reference to `Test::GOOD' 
test.cpp:(.text+0x1f): undefined reference to `Test::BAD' 
collect2: ld returned 1 exit status 

但是,如果我替换此:

localStatus = (num > 2) ? GOOD : BAD; 

与此:

if (num > 2) { 
    localStatus = GOOD; 
} else { 
    localStatus = BAD; 
} 

代码编译并运行正常。什么模糊的C++规则或海湾合作委员会的角落案件负责这种疯狂? (我使用的是Ubuntu 9.10的GCC 4.4.1。)

回答

19

这是根据C++标准。三元运算符确实构成了一个单一的左值,它在运行时将参考GOODBAD。左值与右值转换不会立即应用于左值GOODBAD,因此您需要定义GOODBAD

查看核心语言问题报告http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#712

作为一种变通方法,可以应用显式强制int(读取它们的值,从而做一个左到右值转换),或使用操作,读取数值,像+:为什么

localStatus = (num > 2) ? +GOOD : +BAD; 
+0

标准区分两种情况在哪里?难道他们都“使用”“好”,因此需要一个定义?我认为这只是gcc足够聪明,以避免在左值'GOOD“被用作赋值RHS的情况下的外部链接(因此立即被转换为右值),但在这种情况下还没有管理它在三元运算符中使用的左值“好”,但我准备相信我错了。 – 2011-03-26 23:23:42

+0

@Steve如果你做了'+ GOOD'或者'int a = GOOD',你可以在左值'好好'(直接)“上做右值转换 - 参见3.2p2,在这种情况下你不会”使用“变量)。如果你做'int a = x? a:b;',你可以在左值上进行右值转换,以使三值运算符产生,而不是在a值和b值产生的左值。 – 2011-03-26 23:27:37

+0

啊,你对詹姆斯的评论回答我的问题。它们通过在C++ 03之后插入到草稿中但在2008年出现缺陷之前加以区分。我认为当前的标准完全符合我的说法。我的打印副本和我的PDF(2003)(E)都说:“如果一个对象或非重载函数的名字出现在潜在评估的表达式中,就会使用它。”没有例外。 – 2011-03-26 23:30:30

5
class Test { 
    static const int GOOD = 0; 
    static const int BAD = 1; 
}; 

这些只是声明;他们不是定义。您需要提供的静态成员变量的定义,类的定义之外,在你的.cpp文件之一:

const int Test::GOOD; 
const int Test::BAD; 

另外,对于整型常量,它往往是更方便的使用enum

class Test { 
    enum { 
     GOOD = 0, 
     BAD = 1 
    }; 
}; 
+2

缺乏定义困扰三元运算符而不是标准赋值运算符? – 2011-03-26 23:13:59

+0

这不是那么简单。看到我的答案。 – TonyK 2011-03-26 23:16:24

+0

@Evan:你在谈论哪个赋值运算符?给GOOD和BAD分配值的那个? – 2011-03-26 23:16:37

1

你的代码对我来说看起来很好。并且ideone也同意:请参阅this link。但是这是与gcc-4.3.4。但是,我的gcc-4.4.0不接受它。所以无论什么原因,这并不明显。

编辑补充:在GCC-4.4.0以下变种编译:

int localStatus = 42 ? GOOD : BAD; 

提示:下面的代码无法编译:

int localStatus = (num == 42) ? GOOD : BAD; 

所以有人已经搞砸了某处。

+0

我不确定是否有人在某处搞砸了。我相信,在第一种情况下,唯一发生的事情是,表达式被优化了。但真正的问题仍然存在。 – Petr 2015-06-15 18:04:09

相关问题