2011-03-26 7 views
15

यहां सौदा है। मेरे पास एक स्थिर वर्ग है जिसमें इनपुट प्राप्त करने के लिए उपयोग किए जाने वाले कई स्थिर कार्य शामिल हैं। कक्षा में एक निजी स्थैतिक सदस्य चर शामिल है यह इंगित करने के लिए कि उपयोगकर्ता ने कोई जानकारी दर्ज की है या नहीं। प्रत्येक इनपुट विधि यह देखने के लिए जांचती है कि उपयोगकर्ता ने कोई जानकारी दर्ज की है, और उसके अनुसार स्थिति चर सेट करता है। मुझे लगता है कि यह टर्नरी ऑपरेटर का उपयोग करने का एक अच्छा समय होगा। दुर्भाग्यवश, मैं नहीं कर सकता, क्योंकि संकलक इसे पसंद नहीं करता है।स्थाई सदस्य चर क्यों टर्नरी ऑपरेटर के साथ अच्छी तरह से खेलते हैं?

मैंने समस्या को दोहराया, फिर मेरे कोड को जितना संभव हो सके इसे समझने में आसान बना दिया। यह मेरा मूल कोड नहीं है।

#include "test.h" 

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

यहाँ मुख्य कार्य है::

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

जब मैं इस संकलन करने का प्रयास करें, मैं यह त्रुटि संदेश प्राप्त करें:

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

कोड संकलित करता है तथा अपेक्षा के अनुरूप चलाता है। इस पागलपन के लिए क्या अस्पष्ट सी ++ नियम या जीसीसी कोने का मामला जिम्मेदार है? (मैं Ubuntu 9.10 पर जीसीसी 4.4.1 का उपयोग कर रहा हूँ।)

उत्तर

19

यह सी ++ मानक के अनुसार है। टर्नरी ऑपरेटर एक एकल लैवल्यू बनाता है जो रनटाइम पर GOOD या BAD का संदर्भ देगा।रावल्यू रूपांतरण के लिए लालसा तुरंत lvalue GOOD या BAD पर लागू नहीं होता है, और इसके लिए आपको GOOD और BAD की परिभाषा की आवश्यकता होती है।

कोर भाषा समस्या रिपोर्ट http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#712 देखें।

समाधान के लिए, आप int को स्पष्ट डाले आवेदन कर सकते हैं (जो उनके मूल्यों पढ़ता है, जिससे rvalue रूपांतरण के लिए एक lvalue कर रही है) या एक ऑपरेटर है कि मूल्य पढ़ता है, + की तरह उपयोग करें: क्यों

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

मानक दो मामलों के बीच अंतर कहां है? क्या वे दोनों "अच्छा" का उपयोग नहीं करते हैं, और इसलिए परिभाषा की आवश्यकता होती है? मुझे लगता है कि यह सिर्फ इतना है कि जीसीसी एक असाइनमेंट के आरएचएस के रूप में उपयोग किए जाने वाले लालू 'GOOD' के मामले में बाहरी लिंक से बचने के लिए पर्याप्त स्मार्ट है (और इसलिए तुरंत lvaue-rvalue रूपांतरित हो गया है), लेकिन इस मामले में इसे प्रबंधित नहीं किया है एक ternary ऑपरेटर में इस्तेमाल किया lvalue 'GOOD', लेकिन मैं विश्वास करने के लिए तैयार हूँ कि मैं गलत हूँ। –

+0

@Steve यदि आप '+ GOOD' या 'int a = GOOD' करते हैं, तो आप lvalue' GOOD' ("सीधे" - 3.2p2 देखें, जो इस तरह के मामलों में कहता है कि आप " "चर" का प्रयोग करें। यदि आप 'int = x करते हैं? ए: बी; ', आप लालसा पर रैवल्यू रूपांतरण के लिए लालसा करेंगे जो टर्नरी ऑपरेटर पैदा करता है, न कि' ए' और 'बी 'उपज के अंतराल पर। –

+0

आह, जेम्स के लिए आपकी टिप्पणी मेरे प्रश्न का उत्तर दें। वे सी ++ 03 के बाद ड्राफ्ट में डाले गए टेक्स्ट द्वारा प्रतिष्ठित हैं लेकिन 2008 में उस दोष को उठाए जाने से पहले। मुझे लगता है कि वर्तमान मानक जो मैंने कहा है। मेरी मुद्रित प्रति और 2003 के मेरे पीडीएफ (ई) दोनों कहते हैं, "यदि कोई नाम संभावित रूप से मूल्यांकन की गई अभिव्यक्ति में प्रकट होता है तो एक ऑब्जेक्ट या गैर-अधिभारित फ़ंक्शन का उपयोग किया जाता है।" कोई अपवाद नहीं है। –

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

ये केवल घोषणाओं कर रहे हैं; वे परिभाषा नहीं हैं। आप स्थिर सदस्य चर की परिभाषा अपने सीपीपी फ़ाइलों में से एक में वर्ग की परिभाषा के बाहर, प्रदान करने के लिए, की जरूरत है:,

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

वैकल्पिक रूप से पूर्णांक स्थिरांक के लिए, यह एक enum उपयोग करने के लिए अक्सर अधिक सुविधाजनक है:

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

परिभाषा की कमी टर्नरी ऑपरेटर को परेशान करती है लेकिन मानक असाइनमेंट ऑपरेटर नहीं? –

+0

यह इतना आसान नहीं है। मेरा जवाब देखें – TonyK

+0

@Evan: आप किस असाइनमेंट ऑपरेटर के बारे में बात कर रहे हैं? वह जो अच्छा और बीएडी के लिए मूल्य निर्दिष्ट करता है? –

1

आपका कोड मुझे ठीक लग रहा है। और ideone सहमत हैं: this link देखें। लेकिन यह जीसीसी-4.3.4 के साथ है। हालांकि, मेरा जीसीसी-4.4.0 इसे स्वीकार नहीं करता है। तो जो भी कारण है, यह स्पष्ट नहीं है। निम्नलिखित संस्करण जीसीसी-4.4.0 के तहत संकलित:

int localStatus = 42 ? GOOD : BAD; 

अनुस्मारक: निम्नलिखित कोड संकलन नहीं करता है:

जोड़ने के लिए संपादित

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

तो किसी को खराब कर दिया गया है कहीं।

+0

मुझे यकीन नहीं है कि कोई कहीं कहीं खराब हो गया है। मेरा मानना ​​है कि, पहले मामले में केवल एक चीज होती है, यह है कि अभिव्यक्ति को अनुकूलित किया गया है। लेकिन वास्तविक समस्या अभी भी वहां है। – Petr

संबंधित मुद्दे