2009-04-17 18 views
148

कुछ ऐसा जो मुझे मिल गया है अपने आप को अक्सर हाल ही में कर रही है कि वर्ग के भीतर एक विशेष वर्ग के लिए प्रासंगिक typedefs घोषित किया जाता है, यानीसी ++ में आंतरिक टाइपपीफ - अच्छी शैली या खराब शैली?

class Lorem 
{ 
    typedef boost::shared_ptr<Lorem> ptr; 
    typedef std::vector<Lorem::ptr> vector; 

// 
// ... 
// 
}; 

इन प्रकार तो कोड में कहीं और उपयोग किया जाता है:

Lorem::vector lorems; 
Lorem::ptr lorem(new Lorem()); 

lorems.push_back(lorem); 

कारण मुझे पसंद है यह:

  • यह शोर वर्ग टेम्पलेट्स द्वारा शुरू की कम कर देता है, std::vector<Lorem>Lorem::vector, आदि हो जाता है
  • यह इरादे के बयान के रूप में कार्य करता है - उपर्युक्त उदाहरण में, लोरम क्लास का संदर्भ boost::shared_ptr के माध्यम से गिना जाता है और वेक्टर में संग्रहीत किया जाता है।
  • यह कार्यान्वयन को बदलने की इजाजत देता है - यानी अगर लोरम को बाद में चरणबद्ध रूप से संदर्भित किया जाना चाहिए (boost::intrusive_ptr के माध्यम से) तो इसके बाद कोड पर न्यूनतम प्रभाव होगा।
  • मुझे लगता है कि यह 'सुंदर' दिखता है और पढ़ने के लिए तर्कसंगत रूप से आसान है।

कारण मुझे यह पसंद नहीं है:

  • वहाँ कभी कभी निर्भरता के साथ मुद्दों कर रहे हैं - अगर आप एम्बेड करने के लिए, कहते हैं, एक और वर्ग है, लेकिन केवल जरूरत के भीतर एक Lorem::vector चाहते हैं (या चाहते हैं) घोषित अग्रेषित करने के लिए Lorem (इसके शीर्षलेख फ़ाइल पर निर्भरता पेश करने के विरोध में) तो आप Lorem::ptr के बजाय स्पष्ट प्रकारों (उदाहरण के लिए boost::shared_ptr<Lorem>) का उपयोग करना समाप्त कर देते हैं, जो थोड़ा असंगत है।
  • यह बहुत आम नहीं हो सकता है, और इसलिए समझना मुश्किल है?

मैं अपनी कोडिंग शैली के साथ उद्देश्य बनने की कोशिश करता हूं, इसलिए इस पर कुछ और राय प्राप्त करना अच्छा होगा ताकि मैं अपनी सोच को थोड़ा विच्छेद कर सकूं।

उत्तर

131

मुझे लगता है कि यह उत्कृष्ट शैली है, और मैं इसे स्वयं उपयोग करता हूं। जितना संभव हो सके नामों के दायरे को सीमित करना हमेशा सर्वोत्तम होता है, और कक्षाओं का उपयोग सी ++ में ऐसा करने का सबसे अच्छा तरीका है। उदाहरण के लिए, सी ++ मानक पुस्तकालय कक्षाओं के भीतर typedefs का भारी उपयोग करता है।

+0

यह एक अच्छा मुद्दा है, मुझे आश्चर्य है कि यह 'सुंदर' दिख रहा था, मेरा अवचेतन सौहार्दपूर्ण रूप से इंगित करता था कि सीमित गुंजाइश एक * अच्छी * चीज है। मुझे आश्चर्य है कि, क्या तथ्य यह है कि एसटीएल मुख्य रूप से कक्षा टेम्पलेट्स में इसका उपयोग करता है, यह एक अलग अलग उपयोग करता है? क्या 'कंक्रीट' कक्षा में औचित्य साबित करना मुश्किल है? –

+1

वैसे मानक पुस्तकालय वर्गों की बजाय टेम्पलेट्स से बना है, लेकिन मुझे लगता है कि दोनों के लिए औचित्य समान है। –

2

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

आपको जो कारण पसंद हैं वे अभी भी मेल खाते हैं, क्योंकि उन्हें टाइपेडफ के माध्यम से टाइपिंग एलीज़िंग द्वारा हल किया जाता है, न कि उन्हें अपनी कक्षा के अंदर घोषित करके।

+0

जो टाइप किए गए नामस्थान के साथ गुमनाम नामस्थान को विनियमित करेगा, है ना? टाइपपीफ के साथ समस्या यह है कि यह वास्तविक प्रकार को छुपाता है, जो एकाधिक मॉड्यूल में/में शामिल होने पर संघर्ष कर सकता है, जो खोजने/ठीक करने में मुश्किल होती है। नामस्थानों या कक्षाओं के अंदर इन्हें रखने के लिए यह एक अच्छा अभ्यास है। – Indy9000

+3

नाम विवाद और अज्ञात नेमस्पेस प्रदूषण को कक्षा या बाहर के अंदर टाइपनाम को रखने के साथ बहुत कम करना पड़ता है। आप अपने टाइप के साथ नहीं, अपने वर्ग के साथ एक नाम संघर्ष कर सकते हैं। इसलिए नाम प्रदूषण से बचने के लिए, नामस्थान का उपयोग करें। नामस्थान में अपनी कक्षा और संबंधित टाइपिफ़ी घोषित करें। –

+0

कक्षा के अंदर टाइपपीफ डालने का एक और तर्क templatised कार्यों का उपयोग है। जब, कहें, एक फ़ंक्शन अज्ञात कंटेनर प्रकार (वेक्टर या सूची) प्राप्त करता है जिसमें एक अज्ञात स्ट्रिंग प्रकार (स्ट्रिंग या अपना स्वयं का स्ट्रिंग-अनुरूप संस्करण) होता है। कंटेनर पेलोड के प्रकार को समझने का एकमात्र तरीका typedef 'value_type' के साथ है जो कंटेनर क्लास परिभाषा का हिस्सा है। – Marius

0

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

7

टाइपपेफ निश्चित रूप से अच्छी शैली हैं। और आपके सभी "कारण मुझे पसंद हैं" अच्छे और सही हैं।

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

आप कक्षा के बाहर टाइपपीफ को स्थानांतरित कर सकते हैं लेकिन कक्षा :: पीआरटी क्लासपीआरआर इतनी सुंदर है कि मैं ऐसा नहीं करता हूं। यह मेरे लिए नामस्थानों की तरह है - चीजें दायरे में जुड़े रहती हैं।

कभी कभी मैं

Trait<Loren>::ptr 
Trait<Loren>::collection 
Trait<Loren>::map 

किया और यह सब डोमेन कक्षाओं के लिए और कुछ लोगों के लिए कुछ विशेषज्ञता के साथ डिफ़ॉल्ट हो सकता है।

3

एसटीएल इस तरह की चीज हर समय करता है - टाइपिफ एसटीएल में कई कक्षाओं के लिए इंटरफ़ेस का हिस्सा हैं।

reference 
iterator 
size_type 
value_type 
etc... 

सभी टाइपिफ़ी हैं जो विभिन्न एसटीएल टेम्पलेट कक्षाओं के लिए इंटरफ़ेस का हिस्सा हैं।

+0

सच है, और मुझे संदेह है कि यह वह जगह है जहां मैंने इसे पहले उठाया था। ऐसा लगता है कि यद्यपि यह उचित ठहराना थोड़ा आसान होगा? यदि आप 'मेटा-प्रोग्रामिंग' लाइन के साथ सोचने के लिए होते हैं, तो मैं चर की तरह अधिक होने के रूप में क्लास टेम्पलेट के भीतर टाइपपीफ को देखने में मदद नहीं कर सकता हूं। –

9

टाइपपीफ policy based design and traits सी ++ में निर्मित हैं, इसलिए सी ++ में जेनेरिक प्रोग्रामिंग की शक्ति टाइपपीफ से स्वयं उत्पन्न होती है।

+0

अब इतना नहीं है, क्योंकि हमारे पास अभी 'decltype' है ... – Deduplicator

3

यह एक अच्छा विचार होने के लिए एक और वोट है। मैंने समय और स्थान दोनों में कुशल होने के लिए सिमुलेशन लिखते समय ऐसा करना शुरू कर दिया। सभी मूल्य प्रकारों में एक पीआरटी टाइपपीफ था जो एक साझा साझा सूचक के रूप में शुरू हुआ था। मैंने फिर कुछ प्रोफाइलिंग किया और उनमें से कुछ को एक कोड घुसपैठ करने वाले पॉइंटर में बदल दिया, जहां इन ऑब्जेक्ट्स का इस्तेमाल किया गया था।

ध्यान दें कि यह केवल तभी काम करता है जब आप जानते हैं कि कक्षाएं कहां उपयोग की जा रही हैं, और सभी उपयोगों की एक ही आवश्यकता है। मैं लाइब्रेरी कोड में इसका उपयोग नहीं करता, उदाहरण के लिए, क्योंकि आप लाइब्रेरी को उस संदर्भ में लिखते समय नहीं जानते हैं जिसमें इसका उपयोग किया जाएगा।

9

यह आशय का एक बयान रूप में कार्य करता - ऊपर के उदाहरण में , गर्व द्वारा संचालित कक्षा संदर्भ बढ़ावा :: shared_ptr के माध्यम से गिना जाता है और एक वेक्टर में संग्रहीत करने का इरादा है।

यह वही है जो नहीं करता है।

यदि मुझे कोड में 'Foo :: Ptr' दिखाई देता है, तो मुझे बिल्कुल पता नहीं है कि यह एक साझा_प्टर या फू * है (एसटीएल में :: पॉइंटर टाइपीफिफ हैं जो टी *, याद हैं) या जो भी हो। एएसपी। यदि यह एक साझा पॉइंटर है, तो मैं एक टाइपिफ़ प्रदान नहीं करता हूं, लेकिन साझा_ptr को स्पष्ट रूप से कोड में उपयोग करता हूं।

दरअसल, मैं शायद ही कभी टेम्पलेट मेटाप्रोग्रामिंग के बाहर टाइपपीफ का उपयोग करता हूं।

एसटीएल बात के इस प्रकार हर समय

सदस्य कार्यों और नेस्टेड typedefs के संदर्भ में परिभाषित अवधारणाओं के साथ एसटीएल डिजाइन एक ऐतिहासिक कल-डी-थैली है, आधुनिक टैम्पलेट लाइब्रेरियों मुफ्त का उपयोग करता है फ़ंक्शन और गुण कक्षाएं (सीएफ बूस्ट.ग्राफ), क्योंकि इन्हें अंतर्निहित प्रकारों को अवधारणा को मॉडलिंग से बाहर नहीं किया जाता है और क्योंकि यह उन प्रकार के अनुकूलन प्रकार बनाता है जिन्हें दिए गए टेम्पलेट पुस्तकालयों की अवधारणाओं के साथ दिमाग में आसान नहीं बनाया गया था।

समान गलतियों को करने के कारण एसटीएल का उपयोग न करें।

+0

मैं आपके पहले भाग से सहमत हूं, लेकिन आपका हालिया संपादन थोड़ा छोटा दिखता है। इस तरह के घोंसले प्रकार विशेषता कक्षाओं की परिभाषा को सरल बनाते हैं, क्योंकि वे एक समझदार डिफ़ॉल्ट प्रदान करते हैं। नए 'std :: allocator_traits ' कक्षा पर विचार करें ... आपको लिखने वाले प्रत्येक आवंटक के लिए इसे विशेषज्ञ नहीं करना है, क्योंकि यह सीधे 'Alloc' से प्रकारों को उधार देता है। –

+0

@ डेनिस: सी ++ में, सुविधा लाइब्रेरी/उपयोगकर्ता/पुस्तकालय के पक्ष में होनी चाहिए, न कि उसके/लेखक/के पक्ष में: उपयोगकर्ता एक विशेषता के लिए एक समान इंटरफेस चाहता है, और केवल एक विशेषता वर्ग ही दे सकता है , ऊपर दिए गए कारणों के कारण)। लेकिन यहां तक ​​कि 'एलोक' लेखक के रूप में, आवश्यक टाइप किए गए टाइप किए जाने के बजाय अपने नए प्रकार के लिए 'std :: allocator_traits <>' को विशेषज्ञ बनाना बिल्कुल कठिन नहीं है। मैंने जवाब भी संपादित किया है, क्योंकि मेरा पूरा जवाब एक टिप्पणी में फिट नहीं हुआ है। –

+0

लेकिन यह * उपयोगकर्ता के पक्ष में * है। कस्टम आवंटक बनाने का प्रयास करने वाले 'आवंटक_ट्रेट्स' के * उपयोगकर्ता * के रूप में, मुझे लक्षण वर्ग के पंद्रह सदस्यों से परेशान नहीं होना पड़ेगा ... मुझे बस इतना करना है कि 'typedef Blah value_type;' और प्रदान करें उचित सदस्य फ़ंक्शंस, और डिफ़ॉल्ट 'allocator_traits' बाकी को समझेंगे। इसके अलावा, बूस्ट.ग्राफ का अपना उदाहरण देखें। हां, यह गुण वर्ग का भारी उपयोग करता है ...लेकिन 'graph_traits 'का डिफ़ॉल्ट कार्यान्वयन' अपने स्वयं के आंतरिक टाइपिफ के लिए 'जी' से पूछताछ करता है। –

1

वर्तमान में मैं कोड पर काम कर रहा हूं, जो इस प्रकार के टाइपपीफ का गहन रूप से उपयोग करता है। अभी तक यह ठीक है।

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

तो उन्हें उपयोग करने से पहले, वहाँ कुछ अंक

  • किसी और इन typedefs की आवश्यकता है विचार किया जाना है? क्या वर्ग अन्य वर्गों द्वारा बहुत उपयोग किया जाता है?
  • क्या मैं कक्षा को उपयोग या छुपाता हूं? (छिपाने के मामले में आप इंटरफेस के बारे में भी सोच सकते हैं।)
  • क्या अन्य लोग कोड के साथ काम कर रहे हैं? वह यह कैसे करते हैं? क्या उन्हें लगता है कि यह आसान है या वे भ्रमित हो जाएंगे?
संबंधित मुद्दे