2011-03-26 13 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

相關問題