C++ 为什么不';静态成员变量与三元运算符配合得好吗?
事情是这样的。我有一个静态类,它包含几个用于获取输入的静态函数。该类包含一个私有静态成员变量,用于指示用户是否输入了任何信息。每个输入法检查用户是否输入了任何信息,并相应地设置状态变量。我认为现在是使用三元运算符的好时机。不幸的是,我不能,因为编译器不喜欢这样 我复制了这个问题,然后尽可能简化代码,使其易于理解。这不是我的原始代码 这是我的头文件:C++ 为什么不';静态成员变量与三元运算符配合得好吗?,c++,static,ternary-operator,static-members,C++,Static,Ternary Operator,Static Members,事情是这样的。我有一个静态类,它包含几个用于获取输入的静态函数。该类包含一个私有静态成员变量,用于指示用户是否输入了任何信息。每个输入法检查用户是否输入了任何信息,并相应地设置状态变量。我认为现在是使用三元运算符的好时机。不幸的是,我不能,因为编译器不喜欢这样 我复制了这个问题,然后尽可能简化代码,使其易于理解。这不是我的原始代码 这是我的头文件: #include <iostream> using namespace std; class Test { public:
#include <iostream>
using namespace std;
class Test {
public:
void go ();
private:
static const int GOOD = 0;
static const int BAD = 1;
};
以下是主要功能:
#include <iostream>
#include "test.h"
using namespace std;
int main () {
Test test = Test();
test.go();
return 0;
}
但是,如果我将其替换为:
localStatus = (num > 2) ? GOOD : BAD;
为此:
if (num > 2) {
localStatus = GOOD;
} else {
localStatus = BAD;
}
代码按预期编译和运行。什么模糊的C++规则或GCC角落的情况是造成这种疯癫的原因?(我在Ubuntu 9.10上使用GCC4.4.1。)
这些只是声明;它们不是定义。您需要在类定义之外的一个.cpp文件中提供静态成员变量的定义:
const int Test::GOOD;
const int Test::BAD;
或者,对于整数常量,使用枚举通常更方便:
class Test {
enum {
GOOD = 0,
BAD = 1
};
};
我觉得你的代码很好。并且ideone
同意:请参阅。但gcc-4.3.4就是这样。但是,我的gcc-4.4.0不接受它。所以不管是什么原因,都不明显
编辑以添加:以下变体在gcc-4.4.0下编译:
int localStatus = 42 ? GOOD : BAD;
提醒:以下代码未编译:
int localStatus = (num == 42) ? GOOD : BAD;
有人在某个地方搞砸了。 < P>这是按照C++标准。三元运算符确实构成了一个单独的左值,在运行时将引用GOOD
或BAD
。左值到右值的转换不会立即应用于左值GOOD
或BAD
,因此您需要定义GOOD
和BAD
见核心语言问题报告
作为一种解决方法,您可以将显式强制转换应用于int
(读取其值,从而进行左值到右值的转换)或使用读取值的运算符,如+
:
localStatus = (num > 2) ? +GOOD : +BAD;
为什么缺少定义会困扰三元运算符而不是标准赋值运算符?它不是那么简单。看到我的答案了。@Evan:你说的是哪个赋值运算符?给好的和坏的赋值的那个?@Evan:我不是100%确定,但是我会尝试回答这个问题:当你使用直接赋值时,GOOD
和BAD
只直接用作右值。但是,当您使用条件运算符时,条件表达式num>2?好:BAD
本身就是一个左值表达式,因此左值到右值的转换在选择GOOD
或BAD
之后才正式发生,因此需要实际对象(带定义)。标准在哪里区分这两种情况?它们不是都“使用”GOOD
,因此需要定义吗?我认为gcc足够聪明,可以避免在左值良好
用作赋值RHS的情况下使用外部链接(因此立即进行左值右值转换),但在三元运算符中使用左值良好
的情况下没有管理外部链接,但是我准备相信我错了。@Steve如果你做了+GOOD
或int a=GOOD
,你就在左值GOOD
上进行左值到右值的转换(“直接”-见3.2p2,在这种情况下你不“使用”变量)。如果你做inta=x?a:b
,你将对三元运算符产生的左值进行左值到右值的转换,而不是对a
和b
产生的左值进行转换。啊,你对James的评论回答了我的问题。它们的区别在于在C++03之后但在2008年缺陷出现之前插入到草稿中的文本。我认为目前的标准符合我所说的。我的打印副本和我2003年的PDF(E)都说,“如果对象或非重载函数的名称出现在可能计算的表达式中,则使用该对象或非重载函数。”没有例外。我不确定是否有人在某个地方搞砸了。我相信,在第一种情况下,唯一发生的事情是,表达式被优化了。但真正的问题仍然存在。
int localStatus = 42 ? GOOD : BAD;
int localStatus = (num == 42) ? GOOD : BAD;
localStatus = (num > 2) ? +GOOD : +BAD;