2009-06-25 15 views
5

मैं दो सदस्य कार्यों का हिस्सा है कि कोड का एक टुकड़ा के साथ एक वर्ग है:कोड के दोहराने वाले टुकड़े के लिए सबसे अच्छा कौन सा है?

void A::First() 
{ 
    firstFunctionEpilogue(); 
    sharedPart(); 
} 

void A::Second() 
{ 
    secondFunctionEpilogue(); 
    sharedPart(); 
} 

वर्तमान में firstFunctionEpilogue(), secondFunctionEpilogue() और sharedPart() कॉल लेकिन कोड का सिर्फ टुकड़े से काम नहीं कर रहे हैं, sharedPart() कोड दोहराया जा रहा है। मैं नकल से छुटकारा पाना चाहता हूं।

कोड के साझा टुकड़े को कक्षा के किसी भी सदस्यों तक पहुंच की आवश्यकता नहीं है। तो मैं तीन में से किसी के रूप में इसे लागू कर सकते हैं:

  • एक स्थिर सदस्य समारोह,
  • एक स्थिरांक गैर स्थिर सदस्य समारोह या
  • एक स्थानीय कार्य करते हैं।

कौन सा संस्करण बेहतर है और क्यों?

+0

सिर्फ इसलिए कि कोड का यह भाग दो बार प्रकट होता है, इसका मतलब यह नहीं है कि आपको इसे स्वयं ही एक विधि बनाना है। आप क्या हासिल करना चाहते हैं? –

+1

साझापर्ट() में आप क्या करते हैं यदि यह न तो किसी वस्तु की स्थिति पर निर्भर करता है और न ही बदलता है? – Tobias

+6

@ammoQ: क्या आप दोनों जगहों पर कोड डुप्लिकेट करने का सुझाव दे रहे हैं। यह एक भयानक विचार है। –

उत्तर

5

यदि आपका फ़ंक्शन राज्य तक पहुंचता है लेकिन इसे परिवर्तित नहीं करता है तो एक कॉन्स सदस्य फ़ंक्शन का उपयोग करें।

आपका मामला:

यह आपके समारोह 1) कोड के किसी भी सदस्य के लिए उपयोग की जरूरत है नहीं करता, और 2) उस वर्ग से संबंधित है, तो यह अपने वर्ग के एक स्थिर समारोह बनाते हैं।

इस तरह यह स्पष्ट है कि यह राज्य को संशोधित नहीं कर रहा है, न ही वस्तु की स्थिति पर आधारित है।

एक अतिरिक्त मामले आप का उल्लेख नहीं किया:

एक और बात आप भी कर सकते हैं नहीं है। और यह है कि आपके साझापार्ट को सदस्य फ़ंक्शन पॉइंटर में ले जाएं और उसे कॉल करें और फिर उसके मुख्य निकाय को संसाधित करें। यदि आपके पास बहुत पहले(), सेकेंड(), थर्ड(), चौथा(), ... ऐसे फ़ंक्शंस हैं तो इससे कम कोड डुप्लिकेशन हो सकता है। इस तरह आपको SharePart() को कॉल करने की आवश्यकता नहीं है; प्रत्येक सदस्य फ़ंक्शन के अंत में, और आप कोड के साझापार्ट() को कॉल किए बिना पहले(), द्वितीय(), थर्ड(), ... का पुनः उपयोग कर सकते हैं।

+1

मैं इसे एक गैर-सदस्यीय फ़ंक्शन (शायद यह स्पष्ट करने के लिए एक उप-नामस्थान में छिपा हुआ हूं कि यह सामान्य रूप से उपयोग नहीं किया जाना चाहिए), लेकिन एक स्थिर सदस्य भी काम करेगा। मुख्य बात यह है कि यदि इसे कक्षा के निजी सदस्यों तक पहुंच की आवश्यकता नहीं है, तो उसे * एक्सेस * नहीं होना चाहिए। – jalf

+0

"अगर इसे कक्षा के निजी सदस्यों तक पहुंच की आवश्यकता नहीं है, तो उसे * एक्सेस * नहीं होना चाहिए"। निजी तौर पर मैं इसके बारे में और अधिक परवाह करता हूं अगर यह इस तथ्य के लिए नहीं था कि लगभग सभी सदस्य कार्यों के पास पहले से ही निजी सदस्यों तक पहुंच है, उन्हें विशेष रूप से उपयोग करने की आवश्यकता नहीं है - विशेष रूप से एक सदस्य का उपयोग करने के लिए उन्हें पूरी तरह से पहुंच की आवश्यकता है। कभी-कभी आप खुद को वापस नहीं ले सकते हैं ;-) –

+0

जो कुछ मैं देखता हूं, उससे बहुत से लोगों ने यहां प्रभावी सी ++ पढ़ा है :) स्थानीय कार्यों के लिए –

1

या यह एक अलग वर्ग में हो सकता है।

या, यदि यह सदस्य है, तो यह आभासी हो सकता है।

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

  1. स्थिर पसंद करते हैं, तो ग्राहकों को एक उदाहरण
  2. स्थानीय कार्यों को प्राथमिकता दें बिना कॉल करने के लिए यदि आप ज फ़ाइल को अस्त-व्यस्त नहीं करना चाहती की जरूरत है या आप इसे पूरी तरह ग में छिपा चाहते
+0

+1 .. डुनो क्यों आप डाउनवॉट किए गए हैं – Tom

+0

स्थानीय कार्यों के लिए दृष्टिकोण एक शुद्धता से संबंधित। स्थानीय कार्य डिजाइन सिद्धांतों के बहुत से (अच्छी तरह से, सभी) तोड़ते हैं, लेकिन कभी-कभी व्यावहारिक रूप से सुविधाजनक हो सकते हैं।चूंकि इस प्रश्न को "सर्वोत्तम प्रथाओं" टैग किया गया है - 'गोटो' और 'स्थानीय फ़ंक्शंस' शायद गलत जवाब हैं – ima

+0

मैंने उन्हें प्राथमिकता देने का एक कारण दिया - यदि आपको .h से छिपाने के लिए कुछ चाहिए तो, अन्यथा, शायद उनका उपयोग करें उनका उपयोग न करें। –

3

मैं कहना चाहता हूँ:

  • यह शायद कोई फर्क नहीं पड़ता, तो यह इतना "सर्वोत्तम व्यवहार" नहीं है "के रूप में सिर्फ पागल कुछ भी नहीं करते"।
  • यदि वर्ग और उसके सभी सदस्यों को इसके शीर्षलेख में परिभाषित किया गया है, तो एक निजी स्थैतिक सदस्य समारोह शायद सबसे अच्छा है, क्योंकि यह स्पष्ट रूप से "ग्राहकों के लिए नहीं" इंगित करता है। लेकिन गैर-सदस्य फ़ंक्शन के लिए ऐसा करने के तरीके हैं: इसे दस्तावेज़ न करें, "ग्राहकों के लिए नहीं" टिप्पणी में रखें, और पूरी चीज़ को namespace beware_of_the_leopard में चिपकाएं।
  • यदि क्लास सदस्य फ़ंक्शंस को .cpp फ़ाइल में परिभाषित किया गया है, तो इस तरह के छोटे सहायक फ़ंक्शन .cpp फ़ाइल में निःशुल्क फ़ंक्शंस के रूप में सर्वश्रेष्ठ होते हैं। या तो स्थैतिक, या एक अनाम नामस्थान में।
+0

यह काफी जवाब है जो मैं देने वाला था। यदि इसे कक्षा के सदस्यों तक पहुंच की आवश्यकता नहीं है और केवल क्लास विधियों को कॉल करें, तो इसे क्लास .cpp फ़ाइल में अज्ञात नेमस्पेस में फ़ंक्शन बनाएं। –

0

एक स्थिर सदस्य समारोह, एक स्थिरांक गैर स्थिर सदस्य समारोह या एक स्थानीय कार्य करते हैं।

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

जब तक यह कार्य ऑब्जेक्ट उदाहरण के बाहर से इस फ़ंक्शन को कॉल करने के लिए समझ में आता है, तो यह स्थिर नहीं होना चाहिए। जब तक कि इस वर्ग को आपकी कक्षा तक पहुंचने के बिना कॉल करना समझ में आता है, यह स्थानीय नहीं होना चाहिए।

ब्रायन की टिप्पणी से उधार उदाहरण: यदि यह कार्य वैश्विक स्थिति बदलता है, तो यह वैश्विक स्थिति की कक्षा का सदस्य होना चाहिए; यदि यह फ़ंक्शन फ़ाइल को लिखता है, तो यह फ़ाइल प्रारूप की श्रेणी का सदस्य होना चाहिए; यदि यह रीफ्रेशिंग स्क्रीन है, तो यह सदस्य होना चाहिए ... आदि भले ही यह एक सार्थ अंकगणितीय अभिव्यक्ति है, लेकिन यह कुछ अंकगणित के लिए सदस्य (स्थैतिक या नहीं) को उपयोगी बनाने के लिए उपयोगी हो सकता है।

1

यह एक गैर सदस्य समारोह

कोड के साझा टुकड़ा वर्ग के किसी भी सदस्य के लिए उपयोग की जरूरत नहीं है सुनिश्चित करें।

एक सामान्य नियम के रूप में, यदि कोड के किसी टुकड़े को कक्षा के किसी भी सदस्यों तक पहुंच की आवश्यकता नहीं है तो इसे सदस्य कार्य नहीं करें! जितनी ज्यादा हो सके अपनी कक्षाओं को समाहित करने का प्रयास करें।

मैं एक अलग नामस्थान में एक गैर-सदस्य फ़ंक्शन करने का सुझाव देना चाहता हूं जो सार्वजनिक विधियों को कॉल करेगा और फिर साझा कोड के लिए आपके द्वारा किए गए फ़ंक्शन को कॉल करेगा।

namepsace Astuff{ 
    class A{...}; 

    void sharedPart(){...}; 

    void first(const A& a); 
    void second(const A& a); 
} 

void Astuff::first(const A& a){ 
    a.first(); 
    sharedPart(); 
} 
0

यह एक गैर सदस्य गैर दोस्त समारोह बनाओ:

यहाँ मैं क्या मतलब का एक उदाहरण है। स्कॉट मेयर के इस here (और प्रभावी सी ++ 3 संस्करण के आइटम 23) के लिए एक महान स्पष्टीकरण है।

0

अंगूठे के नियम के रूप में "इसे यथासंभव स्थानीय रखने की कोशिश करें लेकिन आवश्यकतानुसार दिखाई दें"।

यदि फ़ंक्शन को कॉल करने वाले सभी कोड एक ही कार्यान्वयन फ़ाइल में रहते हैं, तो इसका अर्थ यह है कि इसे कार्यान्वयन फ़ाइल में स्थानीय रखें।

यदि आप इसे अपनी कक्षा का एक निजी स्थैतिक तरीका बनाते हैं, तो यह आपके वर्ग सहित कार्यान्वयन द्वारा कॉल करने योग्य नहीं होगा, लेकिन यह अभी भी उनके लिए दृश्यमान होगा।इसलिए हर बार जब आप उस विधि के अर्थशास्त्र को बदलते हैं, तो आपके कॉल सहित सभी कार्यान्वयनों को पुन: संकलित करना होगा - जो कि काफी बोझ है, क्योंकि उनके दृष्टिकोण से, उन्हें उन सिमेंटिक्स को जानने की भी आवश्यकता नहीं है।

इस प्रकार, अनावश्यक निर्भरताओं को कम करने के लिए, आप इसे एक स्थिर वैश्विक कार्य करना चाहते हैं।

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

चाहे आप उस कार्य को नामस्थान में, वैश्विक दायरे में रखते हैं, या एक वर्ग में स्थिर कार्य वास्तव में स्वाद के लिए है।

अंतिम नोट पर, यदि आप वैश्विक स्थैतिक फ़ंक्शन के लिए जाते हैं, तो "अधिक सी ++ जैसे" संस्करण होता है: अनाम नामस्थान। इसमें अच्छी संपत्ति है कि यह वास्तव में राज्य को स्टोर कर सकती है और उपयोगकर्ताओं को अपने किसी भी कार्य को घोषित करने में सक्षम होने के लिए रोकती है।

// in your .cpp file 
namespace /*anonymous*/ 
{ 
    void foo() 
    { 
    // your code here 
    } 
}; 

void MyClass::FooUser1() { foo(); } 
void MyClass::FooUser2() { foo(); } 
संबंधित मुद्दे