2010-03-16 11 views
22
bool is_something_ok(int param,SomeStruct* p) 
{ 
    bool is_ok = false; 

    // check if is_ok 

    if(is_ok) 
     // set p to some valid value 
    else 
     // set p to NULL 
    return is_ok; 
} 

इस समारोह वापसी सच और सेट पी कोई मान्य मान अगर "कुछ ठीक है" के लिए अन्यथा वापसी झूठी और सेट पी शून्य परक्या यह पैरामीटर द्वारा मूल्य वापस करने के लिए एक अच्छा डिजाइन है?

है कि एक अच्छा या बुरा डिजाइन है? व्यक्तिगत रूप से, जब मैं इसका उपयोग करता हूं तो मुझे असहज महसूस होता है। यदि कोई दस्तावेज़ और टिप्पणी नहीं है, तो मुझे वास्तव में यह नहीं पता कि इसका उपयोग कैसे किया जाए।

बीटीडब्लू: क्या एपीआई डिज़ाइन के बारे में कुछ आधिकारिक पुस्तक/आलेख है?

+7

ध्यान दें कि फ़ंक्शन संभवतः पॉइंटर को न्यूल पर सेट नहीं कर सकता है। सूचक की एक प्रति पैरामीटर के रूप में पारित की जाती है, और यहां तक ​​कि अगर वह प्रतिलिपि बनाई जाती है, तो कॉलिंग कोड नोटिस नहीं करेगा। यदि आप सूचक के साथ झुकाव करना चाहते हैं तो आपको संकेत के अतिरिक्त स्तर की आवश्यकता है (इसे पॉइंटर या संदर्भ कहते हैं: 'बूल ऑप (int, someStruct * &)' या 'बूल ऑप (int, someStruct **)' और फिर चीजें प्राप्त होती हैं थोड़ा nastier। –

+0

आप इस उत्तर को देखना चाहते हैं: http://stackoverflow.com/questions/2139224/2139254#2139254 – sbi

उत्तर

12

आप C++ प्रश्न टैग किया है के बाद से और नहीं सी, मैं तुम्हें करने के लिए सुझाव है:

  • वापसी मान सीधे
  • यदि आप एक से अधिक मूल्य है, उत्पादन पैरामीटर का उपयोग
  • आउटपुट पैरामीटर के रूप में गैर-कॉन्स्ट संदर्भों का उपयोग करें जहां संभव हो (पॉइंटर्स के बजाए), और इनपुट पैरामीटर के लिए कॉन्स्ट-रेफरेंस का उपयोग करें।
  • यदि कुछ गलत हो गया है, तो झूठी या -1 लौटने के बजाय अपवाद उठाएं।

लेकिन यह केवल कुछ सामान्य संकेत हैं। हमेशा जाने का सबसे अच्छा तरीका विशिष्ट समस्या पर निर्भर करता है ...

1

मैं शून्य वापस जाने के लिए लगता है कि अगर कुछ ठीक है और वैध SomeStruct नहीं है अगर ठीक बूलियन मान की जाँच के अलावा इस मामले

SomeStruct* is_something_ok(int param); 

में बेहतर इस मामले में आप की जाँच करनी चाहिए यह मान शून्य होगा, और यदि का उपयोग नहीं यह।

लेकिन ऐसे मामले हैं जब आपको पैरामीटर द्वारा मूल्य वापस करना होगा। यह वापसी मूल्यों की संख्या से निर्भर करता है, और संदर्भ समारोह का उपयोग किया जा सकता है।

+0

लेकिन कभी-कभी नल * एक वैध वापसी मूल्य है। –

+0

@ मैथ्यू उस मामले में आप एक परिभाषित करेंगे आपकी कक्षा का विशेष कार्यान्वयन शून्य मूल्य के प्रतिनिधि होने के लिए होता है। फिर कॉलिंग कोड दोनों स्थितियों को उदासीनता से संभाल सकता है। –

+1

जो डिज़ाइन को अधिक जटिल बनाते हैं, यदि आप किसी टीम में काम कर रहे हैं तो चीजों को सरल रखना बेहतर हो सकता है। – Phong

1

आप क्या कर सकते हैं निम्नलिखित:

bool is_something_ok(int param,SomeStruct* p); 

या

// return NULL if the operation failed. 
Somestruct* do_work(int param); 

यह कुछ भी नहीं है काला या सफेद ... (ग्रे है अगर एक डिजाइन/एपीआई अच्छा है या बुरा है कहना मुश्किल है ?!?!?)

आपको एपीआई/मानक चुनना होगा जो आपके लिए कोड करने के लिए आसान होगा। और सुसंगत हो, यदि आप पहली विधि प्रकार चुनते हैं, तो अपनी शेष परियोजना के लिए इसे करें।

अपने कोड को दस्तावेज़ करने के लिए को भी न भूलें, इसलिए यह समझना अधिक आसान होगा कि आपके एपीआई का उपयोग कैसे करें।

2

मुझे ऐसा करने की ज़रूरत है। आपके उदाहरण में विकल्प या तो दो चीजों को एक रिटर्न वैल्यू में एन्कोड करना है (उदाहरण के लिए NULL को विशेष मान के रूप में उपयोग करना) या संरचना को वापस करना।

दो चीजों को एन्कोड करना कभी-कभी असंभव हो सकता है, और थोड़ी सी त्रुटि प्रवण होती है। एक संरचना लौटाना बहुत अधिक काम और अव्यवस्था है। तो मैं ऐसा करता हूं जो आपने किया है। मुझे लगता है कि पैरामीटर सूची में "कच्चे" पॉइंटर्स और संदर्भ मूल्यों को वापस करने के लिए हैं, और वे "कॉन्स्ट" होंगे यदि वे केवल डेटा पास करने के लिए थे।

लेकिन ईमानदार होने के लिए मैं उस नियम को भूल जाता हूं अक्सर मुझे याद है तो शायद यह बहुत अच्छा नहीं है।

एक वर्ग "वैकल्पिक" बढ़ावा पुस्तकालय जो आपकी आवश्यकताओं को हो सकता है में नहीं है, लेकिन मैं वास्तव में कभी नहीं इसे अपने आप को शायद कोई बहुत अच्छे कारण के लिए पसंद आया।

+0

+1 वैकल्पिक रूप से लाने के लिए चर्चा। छोटी फैंसी उपयोगिता जो लगभग हमेशा भुला दी जाती है ... –

3

इस पर निर्भर करता है कि आप 'त्रुटियों' को कैसे संभालना चाहते हैं।

उदाहरण के लिए, मानक फ़ंक्शन atoi ले लो। यह एक स्ट्रिंग को एक पूर्णांक में परिवर्तित करता है, लेकिन यदि स्ट्रिंग में कोई संख्या नहीं है, तो उसे वापस क्या करना चाहिए? इस मामले में, सी/सी ++ रनटाइम गलत वैश्विक चर सेट करेगा। एक अपवाद फेंकने का एक विकल्प होगा।

व्यक्तिगत रूप से, मुझे वास्तव में इन दोनों विकल्पों को पसंद नहीं है। इसलिए, यदि मैं आम तौर पर निम्नलिखित नियम का उपयोग करें:

  • वहाँ संभावित वापसी मान जो एक त्रुटि इंगित करने के लिए इस्तेमाल किया जा सकता की रेंज में एक मूल्य है, और मैं केवल त्रुटि 1 संभव 'की तरह' है? उन मामलों में, मैं त्रुटि इंगित करने के लिए वापसी मान का उपयोग करता हूं। जैसे यदि कर्मचारी नहीं मिला है तो FindEmployee जैसे फ़ंक्शन को न्यूल वापस कर सकता है।
  • यदि सभी संभावित मान फ़ंक्शन द्वारा लौटाए जा सकते हैं (जैसे atoi उदाहरण में), वापसी मान के लिए आउटपुट तर्क का उपयोग करें, और फ़ंक्शन को बूलियन लौटा दें। यदि आपके पास 1 से अधिक संभावित त्रुटि मामले हैं, तो एक enum वापस करें जो कि त्रुटि (या सफलता) की तरह इंगित करता है।
+0

तीसरा विकल्प (जिसे क्यूटी में उपयोग किया जाता है) एक त्रुटि वापसी चर को तर्क के रूप में पास कर रहा है ('int QString :: toInt (bool * error = 0, int base = 0)')। चर्चा में अन्य त्रुटि तंत्र लाने के लिए +1। –

2

मैं कहूंगा कि यह निर्भर करता है। निर्माण की प्रतिलिपि बनाने के लिए आपका प्रकार कितना महंगा है? क्या आप अपना काम RVO लिख सकते हैं-मित्रतापूर्वक? कम से कम जब तक हमारे पास rvalue references के साथ सी ++ 0x नहीं है, तो मेरी सिफारिश "महंगी" प्रकारों (जैसे std::vector<std::string>) वापस नहीं लौटाएगी, बल्कि उन्हें संदर्भ के रूप में पास करें, उदा। का उपयोग करें:

void split(const std::string &txt, char sep, std::vector<std::string> &out); 

बजाय:

std::vector<std::string> split(const std::string &txt, char sep); 

कैसे आप अपने समारोह लिखना तो संभव है कि RVO में शुरू होगा लेकिन मेरे अनुभव में यह कुछ आप आमतौर पर भरोसा कर सकते नहीं है पर निर्भर करता है।

0

आपको boost::optional पर देखना चाहिए जब आप केवल सफलता पर मूल्य वापस करना चाहते हैं।

1

मैं बहुत की तरह सीधे परिणाम प्रकार वापस जाने के लिए सुझाव है:

SomeStruct doSomething(int param) {...} 

और मामलों है कि काम नहीं संभाल कर सकते हैं में एक अपवाद फेंक (tux21b पहले से ही इस तरह से उल्लेख किया)। वैकल्पिक रूप से आप इतना की तरह एक अपवाद फेंकने के बिना std::pair साथ दो प्रकार लौट सकते हैं:

pair<SomeStruct, bool> doSomething(int param) {...} 

और तीसरा मैं संदर्भ के बजाय संकेत (आप की तरह उल्लेख किया) के रूप में उत्पादन मानकों की घोषणा करने क्योंकि बुला कोड में मैं का अंतर देखना चाहते इनपुट और आउटपुट पैरामीटर।

void doSomething(const Somestruct& in, Somestruct* out) {...} 

फिर बुला कोड में यह दिखाई देता है (समारोह घोषणा को देखे बिना) इनपुट और आउटपुट पैरामीटर क्या (अगर मैं consecently इस अवधारणा को लागू) क्या: समारोह को देखते हुए।

SomeStruct a; 
SomeStruct b; 
doSomething(a, &b); // you see a is input, b is output 
2

एपीआई डिज़ाइन के बारे में एक पुस्तक के लिए आपके प्रश्न के संबंध में। मार्टिन रेड्डी द्वारा "एपीआई डिजाइन फॉर सी ++" की तलाश करें, जिसे 2011 में प्रकाशित किया गया था।

स्वीकार्य उत्तर पर टिप्पणी के रूप में। पुस्तक में लेखक वास्तव में आउटपुट पैरामीटर के लिए इनपुट पैरामीटर और पॉइंटर्स के लिए कॉन्स संदर्भों को प्राथमिकता देने का सुझाव देते हैं क्योंकि यह क्लाइंट को अधिक स्पष्ट रूप से इंगित करता है कि पैरामीटर संशोधित किया जा सकता है, उदा। foo (बार) बनाम foo (& बार)।

इसके अलावा आप How To Design A Good API and Why it Matters पर बात देख सकते हैं। जो मुख्य रूप से जावा का उपयोग करता है हालांकि मुझे याद है।

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

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