8

[namespace.udecl]/18 द्वारा कहा गया है:विरासत में प्राप्त कंस्ट्रक्टर्स, डिफ़ॉल्ट निर्माता और दृश्यता

[...] एक का उपयोग कर-घोषणा कि नाम एक निर्माता एक पर्याय नहीं बनाता; इसके बजाए, अतिरिक्त कन्स्ट्रक्टर उपलब्ध हैं यदि वे संबंधित बेस क्लास के ऑब्जेक्ट को बनाने के लिए उपयोग किए जाने पर पहुंच योग्य होंगे, और उपयोग-घोषणा की पहुंच को अनदेखा किया जाएगा। [...]

इस कारण से

, निम्नलिखित कोड संकलन नहीं करता है:

:

class B { protected: B(int) { } }; 
class D: B { using B::B; }; 
int main() { D d{0}; } 

यह एक त्रुटि कम या ज्यादा सभी प्रमुख compilers के साथ एक ही है कि रिटर्न

दूसरी ओर यहां

संरक्षित घोषित, निम्नलिखित कोड को संकलित करता है:

class B { protected: B() { } }; 
class D: B { using B::B; }; 
int main() { D d{}; } 

क्या इसके बजाय पिछले उदाहरण में त्रुटि उत्पन्न करने के कारणों को संकलित करने में विफल नहीं होना चाहिए?
इसे संकलित करने की अनुमति क्या है?

+2

संकेत: 'डी' में उपयोगकर्ता द्वारा घोषित कन्स्ट्रक्टर नहीं है। –

+0

@ टी.सी. मैंने वही सोचा, लेकिन उपयोग-घोषणा की पहुंच को नजरअंदाज कर दिया गया है, इसलिए डिफ़ॉल्ट कन्स्ट्रक्टर को दूसरे मामले में विरासत में सुरक्षित और संरक्षित नहीं किया जाना चाहिए? – skypjack

+0

ठीक है, एक और संकेत। क्लास में कोई उपयोगकर्ता द्वारा घोषित कन्स्ट्रक्टर नहीं है तो [class.ctor]/4 क्या होता है? और यह बेस क्लास कन्स्ट्रक्टर के साथ कैसे इंटरैक्ट करता है, [namepace.udecl]/15 दिया जाता है? –

उत्तर

3

दूसरे मामले के लिए, उत्तराधिकारी विरासत प्रभावी नहीं होता है। deleted implicitly-declared default constructor के नियमों के मुताबिक, दूसरे मामले में वर्ग D उल्लंघन नहीं करता है (D के लिए एक अच्छी तरह से गठित B::B() है); संकलक D के लिए एक इनलाइन सार्वजनिक सदस्य के रूप में एक डिफ़ॉल्ट कन्स्ट्रक्टर घोषित करेगा, जो D d{}; अच्छी तरह से काम करता है।

...

T जो एक नष्ट कर दिया डिफ़ॉल्ट निर्माता है साथ सीधा या आभासी आधार है, या यह अस्पष्ट या इस निर्माता से दुर्गम है।

...

1 मामले के लिए, inheriting constructors प्रभावी होता है:

(जोर मेरा)

अधिभार संकल्प एक विरासत निर्माता का चयन करता है, तो यह सुलभ अगर यह सुलभ जब निर्माण करने के लिए इस्तेमाल किया होगा एक वस्तु इसी आधार वर्ग के : का उपयोग कर-घोषणा की कि वह शुरू की के पहुंच नजरअंदाज कर दिया है।

अधिभार संकल्प विरासत में मिला कंस्ट्रक्टर्स जब ऐसे व्युत्पन्न वर्ग की एक वस्तु को प्रारंभ, तो बेस subobject जहाँ से निर्माता विरासत में मिला था विरासत में मिला निर्माता का उपयोग कर आरंभ नहीं हो जाता, और अन्य सभी ठिकानों और सदस्यों में से एक का चयन करता है के व्युत्पन्न प्रारंभ कर रहे हैं के रूप में यदि डिफॉल्ट की डिफ़ॉल्ट निर्माता द्वारा (डिफ़ॉल्ट सदस्य initializers अगर प्रदान किया जाता है, अन्यथा डिफ़ॉल्ट प्रारंभ जगह लेता है)।

फिर यह अलगाव के कारण विफल हो जाता है।

+0

कॉपी/चाल के बारे में नियम [यहां] (http://eel.is/c++draft/namespace.udecl#4) से आता है, लेकिन जहां से यह डिफ़ॉल्ट रूप से नियम आता है? – skypjack

+0

@skypjack बिंदु यह है कि दूसरे मामले में कक्षा 'डी' के लिए एक डिफ़ॉल्ट कन्स्ट्रक्टर उत्पन्न किया जाएगा, जो * विरासत कन्स्ट्रक्टर * के अलावा प्रभावी होगा। उत्तर तय – songyuanyao

5
class B { protected: B() { } }; 
class D: B { using B::B; }; 
int main() { D d{}; } 

D इस मामले में कोई उपयोगकर्ता-निर्धारित निर्माता है, तो संकलक कि कॉल B::B (लेकिन क्योंकि using, इस मामले में कोई प्रभाव नहीं है इस बात का), कि संकलक आप के लिए एक (सार्वजनिक) उत्पन्न करता है तब उत्पन्न कन्स्ट्रक्टर को मुख्य रूप से बुलाया जाता है।

class B { protected: B(int) { } }; 
class D: B { using B::B; }; 
int main() { D d{0}; } 

भी D ही कोई उपयोगकर्ता परिभाषित निर्माता यहाँ है, संकलक उत्पन्न एक परोक्ष नष्ट कर दिया क्योंकि B केवल एक निर्माता है कि एक int लेता है। D में एक कन्स्ट्रक्टर भी है जो int (using ऐसा करता है) लेकिन इस कन्स्ट्रक्टर को protected चिह्नित किया गया है और इस प्रकार main द्वारा पहुंच योग्य है।

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