2012-04-28 11 views
8

मान लें कि मेरे पास एक गणना है।स्विच के डिफ़ॉल्ट लेबल में क्या रखा जाए?

enum class ShapeName : char {TRIANGLE,CIRCLE,SQUARE}; 

और बाद में मैं इस तरह एक समारोह है:

void Function (ShapeName const shape){ 

    switch (shape){ 
     case ShapeName::TRIANGLE: 
      DoSomething1(); 
      break; 

     case ShapeName::CIRCLE: 
      DoSomething2(); 
      break; 

     case ShapeName::SQUARE: 
      DoSomething3(); 
      break; 

     default: 
      //THIS CODE BLOCK SHOULD NEVER BE EXECUTED! 
    } 

    return; 
} 

हालांकि डिफ़ॉल्ट लेबल क्रियान्वित किया जा कभी नहीं करना चाहिए, मैं संभावित कीड़े पैदा हो सकता के लिए खाते में करना चाहते हैं तो एक प्रोग्रामर के लिए एक और मूल्य कहते हैं 'आकार नाम' और स्विच में इसके लिए जिम्मेदार नहीं है।
आप मेरी क्या सिफारिश करेंगे?

1. दावे
मैं एक अभिकथन इस्तेमाल कर सकते हैं, लेकिन मैं क्या जोर देते हुए कर रहा हूँ?

assert(false); //? 

2. अपवाद
मैं एक अपवाद फेंक सकता है, लेकिन मुझे नहीं लगता कि यह बहुत अच्छा अभ्यास हो जाएगा। मैं इस धारणा के तहत हूं कि अपवाद रन टाइम इवेंट्स के लिए हैं जिन्हें कुछ वातावरण की वजह से भविष्यवाणी नहीं की जा सकती है।

3. बाहर निकलता है
मैं सिर्फ एक त्रुटि के साथ तुरंत कार्यक्रम से बाहर निकल सकते। यह सबसे अच्छा विचार है, लेकिन मुझे यकीन है कि यह अच्छा अभ्यास है। मैंने सोचा कि दावे का लाभ यह था कि जब आप प्रोग्राम को तैयार करते थे तो आप उन्हें बंद कर सकते थे। फिर, वह दावा कोड अब मौजूद नहीं होगा।


शायद एक और तरीका है जिसके बारे में मुझे पता नहीं है। मैं एक कंपाइलर ध्वज का उपयोग करता हूं जो मानों के लिए अनचाहे के बारे में चेतावनी देता है, लेकिन मैं अभी भी जानना चाहता हूं कि दूसरों की क्या सिफारिश है।

+0

4. क्या आप अपने कंपाइलर को चेतावनी देने के लिए कह सकते हैं? यह एक विकल्प है जिसे मैं पुरानी शैली के enums के लिए उम्मीद करता हूँ। –

+0

@SteveJessop g ++ -w -Wall -Wextra -Wswitch -Wswitch-default -Wswitch-enum -std = C++ 0x -o मुख्य main.cpp अजीब, मुझे उपरोक्त कोड के साथ बिल्कुल कोई चेतावनी नहीं मिली। मैंने एक और आकार नाम जोड़ा और डिफ़ॉल्ट लेबल से छुटकारा पा लिया। अब तक कुछ भी नहीं! –

+0

चूहों। सी ++ 11 कार्यान्वयन समाप्त नहीं हुआ है, हालांकि, हम आशा में रह सकते हैं। –

उत्तर

9

मुझे एक सूचनात्मक संदेश के साथ जोर देने का विचार पसंद है। इसे आजमाएं:

assert (!"The default case of so-so switch was reached."); 

यह हमेशा झूठा लौटाता है, लेकिन एक संदेश प्रदान करता है जिसका आप उपयोग कर सकते हैं।

संपादित करें:
मुझे वह स्रोत मिला जो मैंने अपनी धारणा से इस धारणा को खींच लिया; यह निम्नलिखित पुस्तक में है:
सी ++ कोडिंग मानकों - 101 नियम और दिशानिर्देश

+2

या यदि आप वर्तनी के तरीके को पसंद न करें, 'जोर दें (झूठा && "संदेश"); ' –

+3

और याद रखें कि आमतौर पर" रिलीज़ "बिल्ड से आवेषण छीन लिया जाता है। –

+1

रिलीज बिल्ड के लिए, आप ऑप्टिमाइज़ेशन संकेत के रूप में अपने कंपाइलर के बराबर ['__assume (0)'] (http://msdn.microsoft.com/en-us/library/1b3fsfxw.aspx) का भी उपयोग कर सकते हैं। – ildjarn

0

मुझे लगता है कि यह कुछ ऐसा करने पर निर्भर करेगा जो कुछ # विधियों को करता है।

यदि यह बाद में कम गड़बड़ी का कारण बनने जा रहा है तो आप निश्चित रूप से रनटाइम को बाधित करना चाहते हैं, जब इसे "अमान्य enum: enumName" नामक फ़ंक्शन "या डेवलपर अधिसूचना देने के लिए कुछ कहा जाता है जिसे उन्होंने अपडेट नहीं किया है यह स्विच कथन, उन्हें सोचने के बजाय कि कुछ बाद में विफल रहता है।

4

इस विशिष्ट मामले के लिए मेरी वरीयता, जहां आप एक enum टैग पर स्विच कर रहे हैं और सभी मामलों को संभालने, डिफ़ॉल्ट को छोड़ना है। इस तरह, किसी भी उचित कंपाइलर के साथ, अगर कोई एनम में नया टैग जोड़ता है और स्विच पर नहीं, तो आपको स्विच में संभाले जाने वाले टैग के बारे में एक संकलन-समय चेतावनी मिल जाएगी।

+0

स्पष्ट रूप से जीसीसी नए सी ++ 11 एनम कक्षाओं के संबंध में अनुचित है, हालांकि प्रश्नकर्ता जीसीसी का कौन सा संस्करण नहीं कहता है। –

+0

@SteveJessop जीसीसी (उबंटू/लिनारो 4.6.1-9ubuntu3) 4.6.1 –

+0

@ स्टेवेजसेप: जीसीसी (4.4.5, 4.5.2, और 4.6.3 की कोशिश की) मुझे "चेतावनी: गणना मूल्य 'अन्य' स्विच में संभाला गया "" यदि मैं डिफ़ॉल्ट हटा देता हूं और 'अन्य' टैग जोड़ता हूं ... –

0

संक्षिप्त उत्तर: समस्या को खत्म करने के लिए बहुरूपता का उपयोग करें।

लांग जवाब: जड़ समस्या को हल करने का सबसे आसान तरीका (? अर्थात लापता प्रविष्टियों के साथ स्विच बयान को रोकने के लिए) स्विच बयान का उपयोग कर वहाँ प्रविष्टियों का एक मौका भूल की जा रही है कि अगर से बचने के लिए किया जाएगा। स्विच स्टेटमेंट स्थानीय संदर्भों में उपयोगी होते हैं, लेकिन यदि उनके द्वारा प्रस्तुत तर्क कई स्थानों में डुप्लिकेट किया गया है तो एक को अपडेट करना भूलने की संभावना है और आप रनटाइम त्रुटियों के लिए स्वयं को सेट अप कर रहे हैं।

class Shape 
{ 
    // functionality MUST be added for new shape types 
    // or a compile error will occur 
    virtual void DoSomething() const = 0; 
}; 

void Function (Shape const & shape){ 
    return shape.DoSomething(); 
} 

स्विच बयान अभी भी निर्माण के स्थल पर उपयोगी हो सकता है:

enum class ShapeName : char {TRIANGLE,CIRCLE,SQUARE}; 

unique_ptr<Shape> MakeShape (ShapeName const shape){ 
    switch (shape){ 
     case ShapeName::TRIANGLE: 
      return unique_ptr<Shape>(new Triangle()); 

     case ShapeName::CIRCLE: 
      return unique_ptr<Shape>(new Circle()); 

     case ShapeName::SQUARE: 
      return unique_ptr<Shape>(new Square()); 
    } 

    throw std::runtime_error(); 
    // or whichever option you prefer from the other answers 
} 

लेकिन उस केवल जगह तर्क मौजूद है। और यहां तक ​​कि स्थिर बहुरूपता के साथ पर सुधार किया जा सकता है:

enum class ShapeName : char {TRIANGLE,CIRCLE,SQUARE,ELLIPSE}; 

template< ShapeName shape > 
unique_ptr<Shape> MakeShape(); 

template<> 
unique_ptr<Shape> MakeShape<ShapeName::TRIANGLE>() 
{ 
    return unique_ptr<Shape>(new Triangle()); 
} 

template<> 
unique_ptr<Shape> MakeShape<ShapeName::CIRCLE>() 
{ 
    return unique_ptr<Shape>(new Circle()); 
} 

template<> 
unique_ptr<Shape> MakeShape<ShapeName::SQUARE>() 
{ 
    return unique_ptr<Shape>(new Square()); 
} 

int main() 
{ 
    MakeShape<ShapeName::TRIANGLE>(); // okay 

    MakeShape<ShapeName::ELLIPSE>(); // compile error 
} 

अधिक जानकारी के लिए Martin Folwer देखें।

+0

डाउन-वोट क्यों? मुझे लगता है कि इस प्रदूषित उदाहरण के लिए, यह सबसे अच्छा समाधान है। स्विच स्टेटमेंट्स वास्तव में इस कारण से कोड गंध हो सकता है। 'डिफ़ॉल्ट' के साथ समस्या यह है कि आपको छोड़े गए मामले के लिए एक कंपाइलर चेतावनी नहीं मिलती है; बिना 'डिफ़ॉल्ट' के यदि आप स्विच के प्रकार में हैं जहां प्रत्येक मामले में वापसी होती है (उदाहरण के लिए, फैक्ट्री), तो कंपाइलर फ़ंक्शन के अंत में रिटर्न की कमी के बारे में शिकायत करेगा। मुझे लगता है कि एमएसवीसी के पास एक बार पहुंचने योग्य मैक्रो था। –