2011-01-17 11 views
6
#define dItemName  L"CellPhone" 
+0

http://stackoverflow.com/questions/3474949/over-reliance-on-macros/3475032#3475032 – DumbCoder

+0

आप स्कॉट मेयर्स के "प्रभावी सी ++" को देखना चाहते हैं - मुझे लगता है कि तीसरा संस्करण सबसे हालिया है। वह इस और कई अन्य समान सी ++ मुद्दों को संबोधित करने के लिए एक महान काम करता है। – westsider

+0

इस 'ditem नाम' का उपयोग क्या होगा? उदाहरण जोड़ें – i486

उत्तर

13

इसे स्थिर चर के रूप में परिभाषित करें। यह एक अच्छा प्रोग्रामिंग अभ्यास है।

const wchar_t *dItemName = L"CellPhone"; 

मामले में आप कहीं बाद में अपने स्ट्रिंग की लंबाई पता करने की जरूरत है, तो एक सरणी के रूप में यह निर्धारित करें:

const wchar_t dItemName[] = L"CellPhone"; 

इसके अलावा, क्यों #define बुरा है: यह सब स्थानों पर जहां आप का उपयोग बदल देती है एलआईटीमनाम से एल "सेलफोन" शब्द। उदाहरण:

struct { 
    int dItemName; 
} SomeStruct; 

अवैध हो जाएगा: #define साथ

struct { 
    int L"CellPhone"; 
} SomeStruct; 
+0

ठीक है, शाब्दिक पहले से ही दृढ़ता से टाइप किया गया है, लेकिन अल। आप एक * गायब हैं। –

+0

क्या आप '*' या 'std :: wstring' भूल गए थे? –

+0

आप सही हैं, * जोड़ा गया था। –

6

एक प्रमुख समस्या यह है कि यह अपने आप में भाषा के बाहर है और इसलिए एक दिए गए दायरे तक सीमित नहीं है है। आप अनुवाद इकाई में dItemName कहीं भी, सभी नामस्थान, वर्ग, कार्यों में, आदि

का स्थान ले लेगा मैं साथ const std::wstring dItemName = L"CellPhone";

1

#define एक पूर्वप्रक्रमक निर्देश है कि किसी मैक्रो को परिभाषित करता है इसे बदलना चाहते हैं। आपके मामले में मैक्रो dItemName मूल्य L"CellPhone" के साथ।

मैक्रोज़ अधिकतर खराब हैं क्योंकि वास्तविक कोड से पहले उन्हें संसाधित किया जाता है। इसका मतलब है कि वे scopes और सी ++ वाक्यविन्यास के नियमों के अधीन नहीं हैं। यदि आपके पास dItemName नामक एक चर है, तो चीजें शायद काम नहीं करेंगी: आपको इसके कारण संकलन त्रुटियों को समझने में कठिनाई होगी।

समाधान एक चर के रूप में dItemName घोषित करना है (इस मामले में const चर)।

1

क्योंकि प्रीप्रोसेसर मैक्रोज़, जो आपने अभी बनाया है, हर नाम के दायरे को प्रदूषित करें। वे हर जगह उपलब्ध हैं और मानक नामकरण स्कोप नियमों का पालन नहीं करते हैं। इस प्रकार, इस तरह के मैक्रो के साथ, int dItemName = 5; जैसे कोड प्रीप्रोसेसर द्वारा int L"CellPhone" = 5; होने के बजाय feded हो जाता है। एक निरंतर, वैश्विक चर यह नहीं करेगा।

अन्य सभी मुद्दों को एक तरफ, इस IMNSHO मैक्रो परिभाषा के साथ बदतर मुद्दा है।

6

आश्चर्यजनक रूप से मुझे सभी नुकसानों को इंगित करने वाला एक प्रश्न नहीं मिला, यहां तक ​​कि विषय पर पहले भी चर्चा की गई है।

सबसे पहले, C (सी ++ नहीं) में यह निरंतर घोषित करने का तरीका है। यह भी बताता है कि इतने सारे सी ++ डेवलपर्स अभी भी इसका उपयोग क्यों करते हैं: जब वे सी पृष्ठभूमि से आते हैं या सी पृष्ठभूमि वाले लोगों से सिखाए जाते हैं, तो वे इस सी-ईश व्यवहार को पुन: उत्पन्न करते हैं।

सी ++ में, हालांकि, हमारे पास बेहतर सुविधाएं हैं।

#define एक निरंतर परिभाषित नहीं करता है, उसके द्वारा निर्धारित किसी मैक्रो

  1. मैक्रो कोई गुंजाइश नहीं
  2. जानता मैक्रो प्रकार सुरक्षित

मैक्रो कोई गुंजाइश नहीं जानता नहीं है:

वे प्रीप्रोकैसिंग सुविधाएं हैं: प्रीप्रोसेसर अंतर्निहित भाषा (चाहे एएसएम, सी या सी ++) के नियमों से अवगत नहीं है और हमेशा प्रतीकों का विस्तार करेगा यह गुंजाइश के संबंध में स्टॉक में है।

इस कारण से, आमतौर पर मैक्रोज़ को अलग करने के लिए प्रतीकों के एक विशिष्ट सेट का उपयोग करने की अनुशंसा की जाती है। लोग आम तौर पर हालांकि आपको लगता है कि याद रखने की आवश्यकता, ALL_CAPS प्रतीकों का उपयोग:

  • वे लगातार दो अंडरस्कोर शामिल नहीं होना चाहिए
  • वे एक अंडरस्कोर

क्रम सी के अनुरूप होने के में से शुरू नहीं करना चाहिए ++ मानक।

एक मैक्रो सुरक्षित प्रकार नहीं है।

जैसा कि मैंने कहा, पूर्वप्रक्रमक अंतर्निहित भाषा के नियमों पर ध्यान नहीं देता, इसलिए निम्नलिखित यह हड़ताल नहीं करता है के रूप में अजीब:

#define FOO "foo" 

int main(int argc, char* argv[]) 
{ 
    if (FOO) { ... } 

    return 0; 
} 

दूसरी ओर, एक उचित प्रकार का उपयोग कर यह अनजाने में गलती रोका जा सके:

std::string const Foo = "foo"; 

निष्कर्ष?

यदि आप चाहें तो #define का उपयोग कर सकते हैं, यह केवल आप संकलक के बजाय अतिरिक्त काम कर रहे हैं, लेकिन यह आपका कॉल है। व्यक्तिगत रूप से: मैं आलसी हूं :)

+0

मैं एक ओबीजे-सी डेवलपर हूं, हाल ही में मैंने स्थिरांक को स्थिर चर में परिवर्तित करना शुरू कर दिया है (अल केप के उत्तर देखें), जिसे प्रारंभ में मैक्रोज़ परिभाषित किया गया था। यदि कोड निष्पादन और निरंतर परिभाषा के लिए नहीं है, तो क्या #define के लिए कोई अच्छा उपयोग है? (विशेष रूप से, लेकिन विशेष रूप से obj-c के लिए नहीं) –

+0

@YunusNedimMehel: मेरा मुख्य उपयोग केस मैक्रोज़ लॉगिंग कर रहा है। यदि आप उस बिंदु पर '__FILE__'/'__LINE__' तक पहुंच चाहते हैं जहां लॉगिंग लागू की जाती है, मैक्रोज़ आवश्यक हैं, क्योंकि फ़ंक्शंस, यहां तक ​​कि इनलाइन,' __FILE__' /' __LINE__' का उपयोग करेंगे जहां वे परिभाषित किए गए हैं, बिंदु से नहीं -उपयोग का। इसी तरह, सी (सी ++ डब्ल्यू/आरएआईआई और अपवादों में महत्वपूर्ण नहीं) के लिए, एक समारोह में क्लीनअप सेक्शन के नाम के लिए एक परियोजना-व्यापी सम्मेलन होने के बाद, डब्ल्यू/मैक्रोज़ जो रिटर्न की जांच करते हैं और 'क्लियोअप' क्लोजअप सेक्शन नहीं है भयानक (वैकल्पिक तीर-पैटर्न है), और केवल मैक्रोज़ बिंदु-के-उपयोग क्षेत्र में 'goto' कर सकते हैं। – ShadowRanger

1

विफलता के रूप में खोजे जाने वाले कार्यों को परिभाषित करने के लिए इंगित करना - कटाई के लिए चाकू को अच्छी तरह से दोषी ठहराते हुए।

यदि आप उचित रूप से सही नहीं हैं तो UPPERCASE_NAMES के साथ आपकी परिभाषा का नाम दें, आपको परेशानी होगी, लेकिन यदि आप अपनी कार्य शैली को आत्म-अनुशासन नहीं दे सकते हैं तो आपको सी में वैसे भी समस्याएं हो सकती हैं।

आप गतिशील रूप से पुनर्व्यवस्थित सिस्टम उत्पन्न करने के लिए कॉन्स्ट का उपयोग नहीं कर सकते हैं, इसलिए यह किसी भी एम्बेडेड एप्लिकेशन के लिए उपयुक्त नहीं है जो उपयोग के लिए पूर्व-संकलन के अनुरूप है। कॉन्स्ट को केवल पूर्व-मूल्यांकन स्थिरांक असाइन किया जा सकता है, इसलिए अन्य कॉन्स्टेशन अभिव्यक्ति भी नहीं।

सिर्फ इसलिए कि एक उपकरण ओओ-पैराडिग के लिए धनुष नहीं करता है, यह अचानक बेकार नहीं होता है। कॉन्स्टेंस कार्यक्षमता के संबंध में बराबर प्रतिस्थापन नहीं है।

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