दिलचस्प पोस्ट
अक्षर की एक स्ट्रिंग में यूनिकोड एन्कोडिंग के साथ एक स्ट्रिंग कन्वर्ट कैसे करें WPF में WndProc संदेशों को कैसे संभालना है? "अभिव्यक्ति SFINAE" क्या है? चेतावनी: mysqli_query () पैरामीटर 1 को mysqli होने की उम्मीद है, शून्य में दिए गए C ++ संघ सी # में पीएचपी का इस्तेमाल करते हुए एक ज़िप फ़ाइल के रूप में कई फाइलें डाउनलोड करें सभी उपकरणों को फिट करने के लिए एंड्रॉइड स्प्लैश स्क्रीन छवि आकार एक पृष्ठभूमि स्क्रिप्ट से सामग्री स्क्रिप्ट तक संदेश भेजना, फिर इंजेक्शन वाली स्क्रिप्ट के लिए मैं कैसे जांचूं अगर एक तत्व जावास्क्रिप्ट के साथ वास्तव में दिखाई दे रहा है? वर्ग विकल्प का क्या मतलब है? स्ट्रिंग आउटपुट: सी # में प्रारूप या कॉन्सैट? JQuery के बीच का अंतर क्या है: टेक्स्ट () और html ()? मैं एक साधारण शब्दकोश में स्ट्रिंग> asp.net में json को कैसे हटा सकता हूं? वॉली के साथ एंड्रॉइड में "मल्टीपार्ट / फॉर्म-डेटा" पोस्ट कैसे भेजें प्रकार सुरक्षा: अनचेक किए गए कलाकार

सबसे ज्यादा परेशान पार्स: क्यों नहीं ए (()); काम?

स्टैक ओवरफ़्लो ने कई चीजों में से मुझे सिखाया है जो कि "सबसे खराब पर्स" के रूप में जाना जाता है, जिसे क्लासिक रूप से एक पंक्ति के साथ दिखाया गया है जैसे कि

A a(B()); //declares a function 

यद्यपि यह अधिकांश के लिए, सहज रूप से एक प्रकार की A के घोषणापत्र में प्रतीत होता है, एक अस्थायी B ऑब्जेक्ट को एक कंस्ट्रक्टर पैरामीटर के रूप में लेता है, यह वास्तव में फ़ंक्शन की एक एक्शन की घोषणा है, एक फ़ंक्शन को पॉइंटर लेता है जो देता है B और खुद कोई पैरामीटर नहीं लेता है इसी प्रकार लाइन

 A a(); //declares a function 

यह भी उसी श्रेणी के अंतर्गत आता है, क्योंकि किसी ऑब्जेक्ट के बजाय, यह एक समारोह की घोषणा करता है अब, पहले मामले में, इस मुद्दे के लिए सामान्य समाधान B() आसपास एक ब्रैकेट / कोष्ठक के अतिरिक्त सेट जोड़ना है, क्योंकि कंपाइलर एक वस्तु की घोषणा के रूप में इसकी व्याख्या करेगा

 A a((B())); //declares an object 

हालांकि, दूसरे मामले में, ऐसा करने से एक संकलन त्रुटि की ओर जाता है

 A a(()); //compile error 

मेरा सवाल है, क्यों? हां, मैं बहुत अच्छी तरह जानता हूं कि सही 'समाधान' इसे A a; बदलना A a; , लेकिन मैं यह जानने के लिए उत्सुक हूँ कि क्या है कि अतिरिक्त () पहले उदाहरण में कंपाइलर के लिए करता है जो फिर से दूसरे उदाहरण में इसे पुनः उपयोग करते समय काम नहीं करता है। क्या A a((B())); मानक में लिखे एक विशिष्ट अपवाद का हल?

वेब के समाधान से एकत्रित समाधान "सबसे ज्यादा परेशान पार्स: क्यों नहीं ए (()); काम?"

कोई प्रबुद्ध उत्तर नहीं है, यह सिर्फ इसलिए है क्योंकि यह सी ++ भाषा द्वारा वैध वाक्यविन्यास के रूप में परिभाषित नहीं है … तो यह भाषा की परिभाषा के द्वारा ऐसा है,

यदि आपके भीतर कोई अभिव्यक्ति है, तो यह मान्य है। उदाहरण के लिए:

  ((0));//compiles 

भाषाओं को कैसे परिभाषित किया जाता है और कैसे कंपाइलर काम करता है, इस बारे में अधिक जानने के लिए आपको औपचारिक भाषा सिद्धांत या अधिक विशेष रूप से संदर्भ मुक्त ग्रामर्स (सीएफजी) और परिमित राज्य मशीन जैसी संबंधित सामग्री के बारे में सीखना चाहिए। यदि आप इसमें रुचि रखते हैं कि हालांकि विकिपीडिया पृष्ठ पर्याप्त नहीं होंगे, आपको एक किताब मिलनी होगी।

यदि आप कर सकते हैं तो इस मुद्दे का अंतिम समाधान सी + 11 वर्दी आरम्भिकरण वाक्यविन्यास पर जाना है

 A a{}; 

http://www.stroustrup.com/C++11FAQ.html#uniform-init

सी फंक्शन घोषणापत्र

सबसे पहले, सी में सी है, A a() फ़ंक्शन डिक्लेरेशन है। उदाहरण के लिए, putchar में निम्नलिखित घोषणाएं हैं आम तौर पर, ऐसी घोषणाएं हेडर फाइल में संग्रहित होती हैं, हालांकि आप उन्हें मैन्युअल रूप से लिखने से रोकते हैं, अगर आप जानते हैं कि फ़ंक्शन की घोषणा कैसे दिखती है। तर्क नाम घोषणाओं में वैकल्पिक हैं, इसलिए मैंने इसे इस उदाहरण में छोड़ दिया।

 int putchar(int); 

यह आपको इस तरह से कोड लिखने की अनुमति देता है

 int puts(const char *); int main() { puts("Hello, world!"); } 

सी आपको फ़ंक्शन को परिभाषित करने की अनुमति देता है, जो फ़ंक्शन को तर्क के रूप में लेता है, अच्छा पढ़ने योग्य सिंटैक्स के साथ जो फंक्शन कॉल की तरह दिखता है (ठीक है, यह पठनीय है, जब तक आप कार्य करने के लिए कोई संकेतक नहीं लौटाते)।

 #include <stdio.h> int eighty_four() { return 84; } int output_result(int callback()) { printf("Returned: %d\n", callback()); return 0; } int main() { return output_result(eighty_four); } 

जैसा कि मैंने उल्लेख किया है, सी शीर्ष लेख फ़ाइलों में तर्क नामों को छोड़ने की अनुमति देता है, इसलिए output_result शीर्षक फ़ाइल में ऐसा दिखेगा।

 int output_result(int()); 

कन्स्ट्रक्टर में एक तर्क

क्या तुम ये नहीं जानते हो? ठीक है, मुझे आपको याद दिलाने दो।

 A a(B()); 

हां, यह वही फ़ंक्शन घोषणा है A int , a output_result , और B int

आप आसानी से C ++ की नई सुविधाओं के साथ सी के एक संघर्ष को नोटिस कर सकते हैं सटीक होने के लिए, कंसल्टेंट्स को क्लास नेम और कोष्ठक के रूप में, और = बजाय () साथ वैकल्पिक घोषणा सिंटैक्स। डिजाइन से, सी ++ सी कोड के साथ संगत होने की कोशिश करता है, और इसलिए इसे इस मामले से निपटना पड़ता है – भले ही व्यावहारिक रूप से कोई परवाह नहीं करता। इसलिए, पुराने सी सुविधाओं की नई सी ++ सुविधाओं पर प्राथमिकता है घोषणाओं का व्याकरण नाम के रूप में समारोह के रूप में मैच करने की कोशिश करता है, यदि यह विफल रहता है तो () साथ नए सिंटैक्स पर वापस लौटने से पहले।

अगर उन सुविधाओं में से एक मौजूद नहीं है, या एक अलग सिंटैक्स (जैसे {} सी ++ 11 में) था, तो यह मुद्दा एक तर्क के साथ वाक्यविन्यास के लिए कभी नहीं होगा

अब आप पूछ सकते हैं कि A a((B())) काम करता है। ठीक है, आइए output_result को बेकार कोष्ठक के साथ घोषित करें।

 int output_result((int())); 

यह काम नहीं करेगा व्याकरण को वेरिएबल की आवश्यकता होती है जो कि कोष्ठकों में न हो।

 <stdin>:1:19: error: expected declaration specifiers or '...' before '(' token 

हालांकि, सी ++ मानक अभिव्यक्ति की उम्मीद है। सी ++ में, आप निम्न कोड लिख सकते हैं।

 int value = int(); 

और निम्नलिखित कोड

 int value = ((((int())))); 

सी ++ अभिव्यक्ति के रूप में सी प्रकार के उम्मीद के मुताबिक अंदर अंदर कोष्ठक अंदर अभिव्यक्ति की उम्मीद है … अच्छी तरह से … अभिव्यक्ति पैरेन्टेशस का मतलब यहां कुछ भी नहीं है। हालांकि, बेकार कोष्ठकों को सम्मिलित करके, सी फंक्शन घोषित किया गया है, और नए सिंटैक्स का मिलान ठीक तरह से किया जा सकता है (जो सिर्फ एक अभिव्यक्ति की अपेक्षा करता है, जैसे कि 2 + 2 )।

कन्स्ट्रक्टर में अधिक तर्क

निश्चित रूप से एक तर्क अच्छा है, लेकिन दो के बारे में क्या? ऐसा नहीं है कि कन्स्ट्रक्टरों में सिर्फ एक तर्क हो सकता है। अंतर्निहित वर्गों में से एक है जो दो तर्कों को लेता है std::string

 std::string hundred_dots(100, '.'); 

यह सब अच्छी तरह से और ठीक है (तकनीकी तौर पर, इसमें सबसे अधिक परेशान करने वाला पर्स होता है, यदि इसे std::string wat(int(), char()) रूप में लिखा जाएगा, लेकिन आइए ईमानदार हो – यह कौन लिखता है? लेकिन यह मानें कोड में एक परेशानी की समस्या है। आप मान सकते हैं कि आपको कोष्ठक में सब कुछ रखना होगा

 std::string hundred_dots((100, '.')); 

काफी नहीं

 <stdin>:2:36: error: invalid conversion from 'char' to 'const char*' [-fpermissive] In file included from /usr/include/c++/4.8/string:53:0, from <stdin>:1: /usr/include/c++/4.8/bits/basic_string.tcc:212:5: error: initializing argument 1 of 'std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' [-fpermissive] basic_string<_CharT, _Traits, _Alloc>:: ^ 

मुझे यकीन नहीं है कि क्यों जी ++ को कन्वर्ट करने के लिए const char * कन्वर्ट करने का प्रयास करता है किसी भी तरह से, कंस्ट्रक्टर को केवल एक प्रकार के टाइप char साथ बुलाया गया था। इसमें कोई अधिभार नहीं है जिसमें एक प्रकार का तर्क दिया गया है, इसलिए संकलक भ्रमित है। आप पूछ सकते हैं – तर्क चार प्रकार के क्यों है?

 (100, '.') 

हां,, यहाँ एक अल्पविराम ऑपरेटर है अल्पविराम ऑपरेटर दो तर्क लेता है, और सही पक्ष तर्क देता है। यह वास्तव में उपयोगी नहीं है, लेकिन यह मेरी स्पष्टीकरण के लिए जाना जाने वाला कुछ है।

इसके बजाय, सबसे खराब पर्स को हल करने के लिए, निम्नलिखित कोड की आवश्यकता है।

 std::string hundred_dots((100), ('.')); 

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

कन्स्ट्रक्टर में शून्य तर्क

आपने मेरे स्पष्टीकरण में eighty_four कार्य को देखा होगा।

 int eighty_four(); 

हां, यह सबसे अधिक परेशान पर्स से भी प्रभावित होता है। यह एक मान्य परिभाषा है, और आपने सबसे अधिक संभावना देखी है अगर आपने हेडर फाइल बनाई थी (और आपको करना चाहिए)। कोष्ठक जोड़ना इसे ठीक नहीं करता है

 int eighty_four(()); 

ऐसा क्यों हैं? ठीक है, () एक अभिव्यक्ति नहीं है सी ++ में, आपको कोष्ठक के बीच एक अभिव्यक्ति डालनी होगी। आप सी ++ में auto value = () नहीं लिख सकते, क्योंकि () मतलब कुछ भी नहीं है (और यहां तक ​​कि अगर ऐसा होता है, जैसे खाली ट्यूपल (पायथन देखें), यह एक तर्क होगा, शून्य नहीं)। व्यावहारिक रूप से इसका अर्थ है कि आप सी ++ 11 की {} सिंटैक्स का उपयोग किए बिना लघुकथ वाक्यविन्यास का उपयोग नहीं कर सकते, क्योंकि कोष्ठकों में डाल करने के लिए कोई अभिव्यक्ति नहीं है, और फ़ंक्शन घोषणाओं के लिए सी व्याकरण हमेशा लागू होंगे।

आप इसके बजाय हो सकता है

 A a(()); 

उपयोग

 A a=A(); 

आपके उदाहरण में सबसे सरल पैरों एक अभिव्यक्ति होगी, और सी ++ में व्याकरण एक assignment-expression या एक अन्य expression अल्पविराम और अन्य assignment-expression (परिशिष्ट A.4 – व्याकरण सारांश / अभिव्यक्ति) के बाद expression को परिभाषित करता है।

व्याकरण आगे एक assignment-expression को assignment-expression के कई अन्य प्रकारों में से एक के रूप में परिभाषित करता है, जिनमें से कोई भी कुछ नहीं (या केवल सफेद स्थान) हो सकता है

इसलिए आपके पास A a(()) नहीं हो सकता क्योंकि इसका व्याकरण उसे अनुमति नहीं देता है। हालांकि, मैं जवाब नहीं दे सकता कि लोग जिसने सी ++ बना दिया है, इस प्रकार खाली कैरनों का विशेष इस्तेमाल किसी विशेष प्रकार के रूप में करने की अनुमति नहीं देता – मुझे लगता था कि अगर ऐसा होता है तो वे ऐसे विशेष मामले में नहीं डालते हैं एक उचित विकल्प