2015-12-31 10 views
7

मैंने रूपांतरण से संबंधित कई प्रश्नों के माध्यम से ब्राउज़ किया है, लेकिन ऐसा लगता है कि उनमें से कोई भी इस तरह से स्पष्ट कीवर्ड के बारे में चर्चा नहीं कर रहा था।(स्पष्ट शामिल) ऑपरेटर और कन्स्ट्रक्टर रूपांतरण के साथ प्राथमिकता

struct B; 
struct A{ 
    /*explicit*/ A(const B&){ cout << 1; } // *1 
}; 
struct B{ 
    /*explicit*/ operator A()const{ cout << 2; } // *2 
}; 

void foo(const A &){} 

int main(void){ 
    B b; 
    foo(/*static_cast<A>*/ (b)); // *3 
} 

परिणाम:: (Y: uncommented, न: टिप्पणी की, एक्स: या तो) कोड यह

# | *1 | *2 | *3 |output| 
1 | N | N | N |error | 
2 | N | N | Y | 1 | 
3 | N | Y | N | 1 | 
4 | N | Y | Y | 1 | 
5 | Y | N | N | 2 | 
6 | Y | N | Y | 1 | 
7 | Y | Y | N |error | 
8 | Y | Y | Y | 1 | 

1, 7 त्रुटियों अस्पष्ट हैं, जो सामान्य है (और कोई ऑटो रूपांतरण।)
2 ऐसा लगता है कि कन्स्ट्रक्टर की उच्च प्राथमिकता है, लेकिन क्यों?
3, 5 समझने में आसान हैं।
4 अजीब है क्योंकि यह स्पष्ट को कॉल नहीं करता है। क्यूं कर?
6 'स्पष्ट' या कन्स्ट्रक्टर के कारण उच्च प्राथमिकता हो सकता है। कौन सा कारण है? 8 ऐसा लगता है कि कन्स्ट्रक्टर की उच्च प्राथमिकता है, लेकिन क्यों?

क्या कोई कुछ स्पष्टीकरण दे सकता है? धन्यवाद!

+0

यह नियम के अंगूठे का एक कारण है कि आपके पास कनवर्टिंग कन्स्ट्रक्टर और एक रूपांतरण ऑपरेटर दोनों नहीं होना चाहिए - आपको शायद ही कभी यह सही लगे।और जब आप करते हैं, बहुत कम लोग समझते हैं क्यों। –

+0

@ बोपरसन, मुझे यह पता है। मैं इस बारे में उत्सुक हूं कि संकलक इस तरह क्यों काम करता है। यह एक व्यावहारिक सवाल नहीं है, मुझे पता है। धन्यवाद – Asu

उत्तर

2

एक बहुत अच्छा सवाल है।

सबसे पहले, explicit चीज़ का मतलब यह नहीं है कि "स्पष्ट रूपांतरण की आवश्यकता होने पर इसकी प्राथमिकता है"। इसका मतलब है "इस बात को केवल स्पष्ट रूप से बुलाया जा सकता है"। तो यह कुछ स्थितियों को बनाता है जहां इसे नहीं बुलाया जा सकता है, अन्य स्थितियों में इसे लागू करने के लिए मजबूर नहीं किया जाता है।

विचार करने की एक और बात यह है कि static_castdirect initialization है, जबकि फ़ंक्शन पर तर्क देने के दौरान copy initialization है। अन्य चीजों के अलावा, कॉपी प्रारंभिकरण कभी भी स्पष्ट रचनाकारों का उपयोग नहीं करता है। ध्यान देने योग्य एक और बात यह है कि प्रत्यक्ष प्रारंभिक कक्षाओं (स्पष्ट या नहीं) के लिए रचनाकारों का उपयोग आवश्यक है। यद्यपि इसका मतलब यह नहीं है कि रूपांतरण प्रत्यक्ष प्रारंभिक कार्य नहीं कर सकता है: इसका उपयोग किसी कन्स्ट्रक्टर के तर्क को बदलने के लिए किया जा सकता है और यदि कन्स्ट्रक्टर एक कंपाइलर-जेनरेट की गई प्रतिलिपि है, तो यह देखें रूपांतरण फ़ंक्शन प्रदर्शन की तरह प्रत्यक्ष प्रारंभिकरण (जबकि वास्तव में यह प्रतिलिपि निर्माता द्वारा किया गया था)। एक प्रतिलिपि बनाने के बिना एक कॉपी कन्स्ट्रक्टर घोषित करने का प्रयास करें (अक्षम-प्रति तकनीक) और आप देखेंगे कि रूपांतरण फ़ंक्शन सीधे प्रारंभिक संदर्भ में काम नहीं करता है: यह संकलित होगा, लेकिन एक लिंकिंग त्रुटि का कारण बन जाएगा।

इसे ध्यान में रखते

:

  1. स्पष्ट।
  2. प्रत्यक्ष प्रारंभिकरण के लिए एक निर्माता की आवश्यकता होती है, इसलिए इसे लागू किया जाता है।
  3. स्पष्ट।
  4. 2 के समान, वास्तव में। रूपांतरण फ़ंक्शन को घोषित करना explicit केवल इसे लागू होने से रोकता है, यह स्पष्ट संदर्भों में इसका उपयोग लागू नहीं करता है।
  5. स्पष्ट।
  6. फिर से, प्रत्यक्ष प्रारंभिकरण के लिए एक निर्माता की आवश्यकता होती है और यह स्पष्ट लोगों के उपयोग की अनुमति देता है।
  7. स्पष्ट।
  8. एक और प्रत्यक्ष प्रारंभिक मामला।
+0

मैंने foo फ़ंक्शन को शून्य foo (ए) {} में बदल दिया और ए (कॉन्स ए &) = हटाएं; संरचना ए में इसे # 5 और हाँ के मामले में करें, अब यह त्रुटि है। धन्यवाद! – Asu

+0

इसके अलावा, ऐसा लगता है कि इस तरह की "प्राथमिकता" वास्तव में एक अधिभार प्रक्रिया है। एक रूपांतरण कन्स्ट्रक्टर एक सटीक मिलान है, जबकि एक ऑपरेटर रूपांतरण वास्तव में पैरामीटर रूपांतरण के साथ कॉपी कन्स्ट्रक्टर का उपयोग कर रहा है, जो सटीक मिलान नहीं है। उम्मीद है कि मैंने इसे गलत समझा नहीं है। – Asu

+0

@Asu, अधिक सटीक होने के लिए, इसे अधिभार _resolution_ प्रक्रिया कहा जाता है, लेकिन हां, यह सामान्य विचार है। और मुझे नहीं लगता कि आपको 'foo' हस्ताक्षर बदलने की जरूरत है। संदर्भ या नहीं, चूंकि वास्तविक पैरामीटर का प्रकार औपचारिक पैरामीटर के प्रकार से अलग है, इसलिए कंपाइलर को अभी भी एक प्रतिलिपि बनाने की आवश्यकता है, या तो इसे स्वयं या इसे संदर्भित करने के लिए। –

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