2012-01-07 7 views
16

यह एक स्पष्ट उत्तर या डुप्लिकेट के साथ एक प्रश्न हो सकता है। यदि हां, तो क्षमा करें, मैं इसे हटा दूंगा।डिज़ाइनरों को डिफॉल्ट कन्स्ट्रक्टर या विनाशकों की तरह "जंजीर" क्यों कॉपी नहीं किया जाता है?

प्रतिलिपि बनाने वाले कन्स्ट्रक्टर (डिफॉल्ट सीटीर्स या डाटर) की प्रतिलिपि क्यों नहीं बनाते हैं ताकि व्युत्पन्न वर्ग की कॉपी कन्स्ट्रक्टर को बुलाया जा सके, बेस क्लास की कॉपी कन्स्ट्रक्टर को बुलाया जाता है? प्रतिलिपि बनाने वाले और विनाशकों के साथ, उन्हें आधार-से-व्युत्पन्न और व्युत्पन्न-आधार पर क्रमशः श्रृंखला में बुलाया जाता है। प्रतिलिपि बनाने वालों के लिए यह मामला क्यों नहीं है? उदाहरण के लिए, इस कोड:

class Base { 
public: 
    Base() : basedata(rand()) { } 

    Base(const Base& src) : basedata(src.basedata) { 
     cout << "Base::Base(const Base&)" << endl; 
    } 

    void printdata() { 
     cout << basedata << endl; 
    } 

private: 
    int basedata; 
}; 

class Derived : public Base { 
public: 
    Derived() { } 

    Derived(const Derived& d) { 
     cout << "Derived::Derived(const Derived&)" << endl; 
    } 
}; 


srand(time(0)); 


Derived d1;  // basedata is initialised to rand() thanks to Base::Base() 

d1.printdata(); // prints the random number 

Derived d2 = d1; // basedata is initialised to rand() again from Base::Base() 
       // Derived::Derived(const Derived&) is called but not 
       // Base::Base(const Base&) 

d2.printdata(); // prints a different random number 

प्रतिलिपि निर्माता वास्तव में वस्तु की एक प्रति क्योंकि Derived::Derived(const Derived&)basedata उपयोग नहीं कर सकते इसे बदलने के लिए बनाने के (नहीं कर सकते हैं) नहीं है।

क्या कुछ मूलभूत है जो मैं प्रतिलिपि बनाने वालों के बारे में याद कर रहा हूं ताकि मेरा मानसिक मॉडल गलत हो या क्या इस डिजाइन के लिए कुछ आर्केन (या आर्केन) कारण नहीं है?

+0

@ybungalobill ने दिखाया है कि यह संभव है, और काफी आसान है। मुझे लगता है कि आपका सवाल है "वे स्वचालित रूप से *** क्यों नहीं बंधे *** ***?" –

+0

@AaronMcDaid हाँ, यह मेरा प्रश्न है, लेकिन इसका भी उत्तर –

+0

@BenVoigt हाँ से नीचे दिया गया है, मैं सोच रहा था कि एक स्पष्ट रूप से लिखित एक स्पष्ट रूप से लिखित कन्स्ट्रक्टर की तरह क्यों नहीं है। लेकिन इस प्रश्न का उत्तर पहले ही दिया गया था –

उत्तर

17

प्रतिलिपि निर्माता वास्तव में वस्तु की एक प्रति क्योंकि Derived::Derived(const Derived&)pdata उपयोग नहीं कर सकते इसे बदलने के लिए बनाने के (नहीं कर सकते हैं) नहीं है।

ज़रूर यह कर सकते हैं:

Derived(const Derived& d) 
    : Base(d) 
{ 
    cout << "Derived::Derived(const B&)" << endl; 
} 

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

के लिए यह मामला है: किसी प्रतिलिपि निर्माता को किसी अन्य निर्माता से अलग क्यों होना चाहिए? एक व्यावहारिक समस्या के एक उदाहरण के रूप में:

struct Base 
{ 
    Base() { } 
    Base(Base volatile&) { } // (1) 
    Base(Base const&) { } // (2) 
}; 

struct Derived : Base 
{ 
    Derived(Derived&) { } 
}; 

Base प्रतिलिपि कंस्ट्रक्टर्स आप Derived प्रतिलिपि निर्माता कॉल की उम्मीद करेंगे?

+0

ऐसा लगता है कि यह _is_ अलग है। डिफ़ॉल्ट कन्स्ट्रक्टर हर दूसरे कन्स्ट्रक्टर से अलग क्यों होना चाहिए? –

+1

क्योंकि केवल एक डिफ़ॉल्ट कन्स्ट्रक्टर हो सकता है। –

+2

डिफ़ॉल्ट कन्स्ट्रक्टर अन्य लोगों से अलग नहीं है। सभी रचनाकारों के लिए, जब तक बेस क्लास प्रारंभिक सूची में स्पष्ट रूप से निर्दिष्ट नहीं किया जाता है, तो यह डिफ़ॉल्ट रूप से बनाया जाएगा, जैसे कि सभी सदस्य जो प्रारंभकर्ता सूची में निर्दिष्ट नहीं हैं, डिफ़ॉल्ट रूप से निर्मित किए जाएंगे। – DRH

3

आप कर सकते हैं:

Derived(const Derived& d) : Base(d) { 
    cout << "Derived::Derived(const B&)" << endl; 
} 

यह d की Base उप वस्तु पर Base प्रतिलिपि निर्माता कहता है।

'क्यों' के लिए उत्तर मुझे नहीं पता। लेकिन आमतौर पर कोई जवाब नहीं है। समिति को सिर्फ एक विकल्प या दूसरा चुनना पड़ा। यह शेष भाषा के साथ अधिक संगत लगता है, जहां उदा। Derived(int x) स्वचालित रूप से Base(x) पर कॉल नहीं करेगा।

+0

आह, मैं इस फीचर के बारे में भूल गया, लेकिन यह डिफ़ॉल्ट क्यों नहीं है? –

+3

@ सेठ: डिफ़ॉल्ट प्रति-कन्स्ट्रक्टर अपनी प्रतिलिपि बनाने वाले को कॉल करके बेस क्लास (एसएस) समेत सभी सबोबजेक्ट्स कॉपी करता है। –

+0

@BenVoigt क्षमा करें , मेरा मतलब है कि यह स्वयं लिखित प्रतिलिपि ctors का डिफ़ॉल्ट व्यवहार क्यों नहीं है, क्यों नहीं यह डिफ़ॉल्ट प्रतिलिपि ctor करता है। –

2

ऐसा इसलिए है क्योंकि हर निर्माता डिफ़ॉल्ट रूप से डिफ़ॉल्ट आधार निर्माता कहता है:

Derived(const Derived& d) { 
    cout << "Derived::Derived(const B&)" << endl; 
} 

Base() कॉल करेंगे।

यह मानक द्वारा परिभाषित किया गया है। मैं इसे कक्षा में कॉपी कन्स्ट्रक्टर को कॉल करने के बजाय इसे पसंद करता हूं। आप निश्चित रूप से इसे स्पष्ट रूप से कॉल कर सकते हैं।