2010-12-27 13 views
6

टाइपपीफ की मेरी समझ एक उपनाम घोषित करना है। इंटेल के लिए इस तरह की घोषणा अब इंटीजर के रूप में संदर्भित की जाएगी। पर क्यों? कोई टाइपिफ़ का उपयोग क्यों करेगा? अधिक फायदेमंद कारण क्या है?सी ++ टाइपपीफ का उपयोग क्यों करें?

typedef int Integer; 

Integer blamo = 50; 

cout << blamo << endl; 
+0

[सी ++ टाइपपीफ प्रश्न ... आसान एक ..] (http://stackoverflow.com/questions/1664028/c-typedef-question-easy-one) के संभावित डुप्लिकेट – marcog

उत्तर

18

कि एक अच्छा उदाहरण नहीं है क्योंकि Integer और int किसी भी अलग अर्थ नहीं है। लेकिन कुछ की तरह कल्पना,

typedef int BlamoType; 

अब, भविष्य में जब 'blamo' एक 64-बिट पूर्णांक हो जाता है, तो आप सिर्फ इस typedef बदल सकते हैं, और सभी अन्य कोड जैसा ही हो।

टाइपपीफ का एक और कारण टाइप नामों को छोटा करना है।

boost::shared_ptr<std::map<std::wstring, std::vector<int> > > blamo1; 
boost::shared_ptr<std::map<std::wstring, std::vector<int> > > blamo2; 
std::vector<boost::shared_ptr<std::map<std::wstring, std::vector<int> > > > blamoList; 

के बजाय उदाहरण के लिए आप कर सकते हैं:

typedef boost::shared_ptr<std::map<std::wstring, std::vector<int> > > BlamoType; 
BlamoType blamo1; 
BlamoType blamo2; 
std::vector<BlamoType> blamoList; 
+1

यह भी एक महान उदाहरण है टाइपपीफ के साथ समस्या: "भविष्य में जब 'ब्लमो' 64-बिट पूर्णांक बन जाता है।" जब मेरा कोड टूट जाता है क्योंकि किसी ने उस प्रकार को बदल दिया है जिसे मैं परिभाषा को ट्रैक किए बिना देख नहीं सकता। – Jay

+3

जय: यह सामान्य वर्ग के आंतरिक परिवर्तनों को बदलने से अलग कैसे होता है? – phlip

+3

@Jay यह नहीं है कि किसी भी encapsulation के साथ समस्या है? क्या आप encapsulation के खिलाफ हैं? – tenfour

7

तो आप केवल एक बार टाइप करने के लिए boost::shared_ptr<std::map<std::string,std::string>> है?

+0

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

2

The power of 'typedef' in C++ का कहना है:

सी ++ अन्य मौजूदा डेटा प्रकार के आधार पर हमारे अपने प्रकार की परिभाषा की अनुमति देता है। हम कीवर्ड टाइपपीफ का उपयोग करके ऐसा कर सकते हैं, जिसका प्रारूप है:

typedef exist_type new_type_name;

जहां existing_type एक सी ++ मौलिक या यौगिक प्रकार है और new_type_name नई प्रकार हम परिभाषित कर रहे हैं के लिए नाम है।

उदाहरण के लिए:

typedef char C; 
typedef unsigned int WORD; 
typedef char * pChar; 
typedef char field [50]; 

Some more detail about typedef Specifier


+1

7.1.3 [डीसीएल।typedef] कहते हैं 'एक टाइपिफ़-नाम इस प्रकार एक और प्रकार के लिए समानार्थी है, इसलिए आप अपने स्वयं के प्रकार को परिभाषित नहीं कर सकते हैं, आप बस एक और प्रकार के उपनाम कर सकते हैं। यह एक महत्वपूर्ण अंतर है, क्योंकि एलियास को अन्य रूपों में "रूपांतरित" (यहां तक ​​कि) भी नहीं किया जा सकता है जो समान परिभाषा साझा करते हैं, नए प्रकार डिफ़ॉल्ट रूप से अन्य प्रकारों में परिवर्तित नहीं हो सकते हैं। प्रोग्रामिंग भाषा डी'एस 'टाइपपीफ 'वास्तव में नए प्रकार पेश करती है, और इसमें सी ++ में' टाइपपीफ 'के लिए' उपनाम 'है। रीयल टाइपिफ्स टाइपएफ़ फ़ंक्शन तर्क सूचियों के लिए दिलचस्प हैं (सोचें 'कोण (डिग्री (10))', लेकिन सी ++ के उपनाम नहीं हैं। –

+0

मुझे इस परिभाषा को लगता है कि टाइपपीफ कैसे काम करता है जब आप टाइपिंग के रूप में ऐसी चीजों को देखते हैं फंक्शन पॉइंटर्स का। यहां तक ​​कि जब भी आप परिभाषा को देखते हैं और फिर सरणी टाइपपीफ को देखते हैं, तो यह वही नहीं दिखता है। जब मुझे अंत में एहसास हुआ कि आप सामान्य रूप से परिभाषा लिखते हैं लेकिन नए प्रकार के नाम का उपयोग जगह में करते हैं परिवर्तनीय नाम के और फिर टाइपिफ़ को जोड़ें, यह मेरे लिए बहुत स्पष्ट हो गया है। – Firedragon

0

अन्य उदाहरण जहां यह समझ में आता है, एक डेटा प्रकार के लिए एक संक्षिप्त शॉर्टेंड होना चाहिए जो संरचना के सूचक के रूप में लागू किया गया था।

2

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

4

विचार करने के लिए एक और मामला; समारोह प्रोटोटाइप/पॉइंटर्स। क्या आप इसे हर बार लिखना चाहते हैं जब आप एक विधि को परिभाषित करते हैं जो फ़ंक्शन पॉइंटर को तर्क के रूप में लेता है?

int Search(void* key, void* array, int len, int (*someFunc)(void*, void*)) 
{ 
    // do stuff, call passed in function, etc. 
} 

मैं नहीं बल्कि यह इस तरह से

typedef int (*ComparisonFunc)(void*, void*) 

int Search(void* key, void* array, int len, ComparisonFunc fn) 
{ 
    // do stuff, call passed in function, etc. 
} 

यहां सी तुलना समारोह माफ कर करना होगा, अवधारणा सी में लागू होता है ++ रूप में अच्छी तरह (लेकिन आप संकेत शून्य करने के लिए के मामले में जेनरिक लागू नहीं होता बेशक)

3

ठीक है, यह सुनिश्चित है कि नाम अधिक verbose नाम नहीं है।

तीन मुख्य कारण हैं।

एक, नाम कम वर्बोज़ & टाइप करने में आसान बनाने के लिए। कक्षाओं और/या टेम्पलेट्स से निपटने के दौरान अक्सर यह लाभ खेलने के लिए आता है। उदाहरण के लिए, यदि आप एक एक string के बीच map और कुछ वस्तु है, एक typedef का उपयोग कर इस तरह निर्माणों को कम करके मदद कर सकते हैं:

for(std::map<string, MyObj>::iterator it = my_map_.begin(); it != my_map_.end(); ++it) 
इस के लिए

:

typedef std::map<string, MyObj> MyMap; 
for(MyMap::iterator it = my_map_.begin(); it != my_map_.end(); ++it) 

उपयोगिता कितनी बार के लिए आनुपातिक है आपको MyObjMap के प्रकार की घोषणा करने की आवश्यकता है। सिर्फ एक बार? इतना उपयोगी नहीं है। एक हजार गुणा? बहुत उपयोगी यह कोड को और अधिक स्पष्ट बनाने में मदद करता है & स्वयं-दस्तावेज़, विशेष रूप से जब आप इन प्रकार की कई वस्तुओं की घोषणा करते हैं।

दूसरा कारण संभवतः एक विरोधी कारण भी है। यह सामान्यता और विस्तारशीलता का एक निश्चित स्तर प्राप्त करने का प्रयास करने के लिए किया जाता है। यह विशेष रूप से कक्षा के सदस्य प्रकारों के साथ किया जाता है। विचार है कि अपने वर्गों को अधिक सामान्य बनाएं ताकि जब आप सदस्यों के प्रकार बदलते हैं, तो आपको कॉलिंग कोड बदलना नहीं पड़ता है। लेकिन मैं उल्लेख करता हूं कि यह एक विरोधी कारण भी हो सकता है क्योंकि लोग अक्सर सोचते हैं कि इससे वास्तव में इससे अधिक लाभ होता है। वाप्स सॊचो। आप कितनी बार वास्तव में किसी सदस्य के प्रकार को से __int64 पर बदलते हैं? कुछ बार, शायद? क्या यह कोडिंग पैटर्न स्थापित करने के लिए वास्तव में पर्याप्त है?

एक अंतिम कारण वास्तव में एक डिग्री के लिए पहले का विस्तार है। कार्यों के लिए पॉइंटर्स के लिए सुविधाजनक नाम प्रदान करने के लिए।

+2

मुझे "यह कोड को और अधिक स्पष्ट और स्वयं-दस्तावेज़ बनाने में भी मदद करता है" से असहमत होना चाहिए। जब ​​मुझे कोड मिलता है जो टाइपिफ़ का उपयोग करके चर घोषित करता है I टी में एक संकेत है कि वास्तव में वह चर क्या है। "ValueType x;" टाइप करना आसान है लेकिन मुझे इस प्रकार के बारे में कुछ भी नहीं बताता है। – Jay

+2

@Jay: यदि आपको अंतर्निहित प्रकार जानने की आवश्यकता है, तो मैं सहमत हूं। यह हमेशा नहीं है * उपयोगी। लेकिन कई मामलों में , यदि कक्षा अच्छी तरह डिज़ाइन की गई है, तो आपको अंतर्निहित प्रकार को जानने की आवश्यकता नहीं हो सकती है। –

11

एक कारण है कि यहां कोई भी उल्लेख नहीं किया गया है: जेनेरिक कोड लिखने के लिए। std::vector जैसे कुछ कंटेनर के कार्यान्वयन पर विचार करें।

template<class Container> void f(const Container &c) 
{ 
    typename Container::value_type v = c.back(); 
    // ... 
} 

आप अपने वर्ग में इस तरह के एक प्रकार लागू कर सकते हैं: यह एक प्रकार std::vector<T>::value_type इसलिए किसी को भी कहा जाता है कि लिखते हैं सामान्य कोड यह इस्तेमाल कर सकते हैं होना चाहिए?एक ही रास्ता एक typedef है:

// !!!EXPOSITION ONLY!!! 
template<class T> class vector 
{ 
public: 
    typedef T value_type; 
    // ... 
}; 
3

वहाँ कम से कम 3 कारणों क्यों मैं typedefs का उपयोग कर रहे हैं, सबसे/जो सभी के पहले से ही जवाब में शामिल किया गया है:

- सरलीकरण:

typedef int (*funcptr)(char, unsigned long); 
funcptr f; // f is a ptr to a function taking char & unsigned long, returning an int 

typedef std::vector<Record> Container; 
Container c; // c is a vector of Records 

- कैप्सूलीकरण:

typedef unsigned short int MY_COUNTER; 
MY_COUNTER c; 

अब अगर बाद में, मैं MY_COUNTER बड़ा बनाना चाहता हूं, तो मैं सिर्फ टाइपपीफ बदलता हूं और सभी काउंटर-संबंधित कोड अपडेट किया जाता है (एक पुन: संकलन के बाद)। ध्यान दें कि अगर मैंने काउंटर के लिए स्पष्ट रूप से हर जगह unsigned short int का उपयोग किया था, तो मुझे सभी फाइलों के माध्यम से जाना होगा, और काउंटर के लिए केवल unsigned short int उपयोगों को बदलना होगा; मैं सिर्फ वैश्विक स्तर पर unsigned short int को सभी कोड में प्रतिस्थापित नहीं कर सकता क्योंकि मैं इसे काउंटर के अलावा अन्य चीजों के लिए उपयोग कर सकता हूं।

- पोर्टेबिलिटी

typedef unsigned short UINT16; 

अब जब मैं एक अलग मंच पर जाने के लिए, मैं सिर्फ नक्शा एक ही स्थान पर (हेडर फाइल) में कुछ और (जैसे, unsigned long) को UINT16, लेकिन मेरे सारे कोड अभी भी काम करता है (एक पुन: संकलन के बाद)। लगभग "फ़ायरवॉल टाइप करें" की तरह - यह प्लेटफ़ॉर्म परिवर्तनों को पूरे कोड में परिवर्तनों में फैलाने से रोकता है। कोई भी डेवलपर (विशेष रूप से एम्बेडेड डेवलपर्स जो हमेशा कई आर्किटेक्चर & प्लेटफॉर्म पर डब्ल्यू/कोड से निपट रहे हैं) जिन्हें कभी भी एक बड़े सी या सी ++ कोडबेस & से गुजरना पड़ता है int से short int की सभी घटनाओं को बदलना या जो भी इससे संबंधित होगा।

ध्यान दें कि किसी भी हाल ही संकलक के लिए,stdint.hका उपयोग अक्सर उपलब्ध & मंच पोर्टेबिलिटी दृष्टिकोण के लिए एक बेहतर तरीका है। लेकिन मैं कई प्रणालियों पर काम करता हूं जहां संकलक पुराना है &stdint.hमौजूद नहीं है (या बनाया जाना है)।


typedefs के लिए अन्य अच्छे उपयोग के बहुत सारे हैं, तो आप टेम्पलेट के साथ अधिक काम करने के लिए विशेष रूप से के रूप में है, लेकिन इन 3 स्थितियों सबसे आम उपयोगी और सहज ज्ञान युक्त/स्पष्ट का उपयोग करता है (कम से कम IMO) से कुछ हैं।

+0

ग्रेट उत्तर, बहुत अंडररेड! – Konstantin

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