2011-09-08 18 views
26

में चेनिंग निर्माता श्रृंखलन की मेरी समझ है कि, जब एक वर्ग में एक से अधिक निर्माताओं (अतिभारित कंस्ट्रक्टर्स), देखते हैं अगर उनमें से एक दूसरे के निर्माता तो कॉल करने के लिए, इस प्रक्रिया निर्माता श्रृंखलन कहा जाता है की कोशिश करता है, जो सी ++ में समर्थित नहीं है। हाल ही में मैं ऑनलाइन सामग्री को पढ़ने के दौरान इस पैरा में आए .... यह इस तरह से चला जाता है ...निर्माता सी ++

आप स्थिति है जहाँ आप के लिए एक सदस्य समारोह लिखना चाहते हैं में अपने आप को मिल सकता है एक वर्ग वापस पुनः आरंभ कर देगा डिफ़ॉल्ट मानों के लिए। क्योंकि आपके पास पहले से ही एक कन्स्ट्रक्टर है जो ऐसा करता है, आप अपने सदस्य फ़ंक्शन से कन्स्ट्रक्टर को कॉल करने का प्रयास करने के लिए लुभाने वाले हो सकते हैं। जैसा कि बताया गया है, सी ++ में कन्स्ट्रक्टर कॉल चेनिंग अवैध है। आप अपने फ़ंक्शन में कन्स्ट्रक्टर से कोड कॉपी कर सकते हैं, जो काम करेगा, लेकिन डुप्लिकेट कोड का नेतृत्व करेगा। इस मामले में सबसे अच्छा समाधान कन्स्ट्रक्टर से कोड को अपने नए फ़ंक्शन में ले जाना है, और कन्स्ट्रक्टर डेटा को प्रारंभ करने के काम को करने के लिए अपने फ़ंक्शन को कॉल करना है।

निर्माता भी निर्माता श्रृंखलन के दायरे में आ बुला एक सदस्य समारोह करता है ?? कृपया इस विषय पर सी ++ में कुछ प्रकाश डालें।

+3

मैं नहीं कह चाहते हैं, और यह एक गैर sequitur है लेख कहने के लिए कि निर्माता श्रृंखलन अवैध है, तुरंत कह कुछ मनमाने ढंग से सदस्य समारोह (जरूरी नहीं एक निर्माता) सोच सकते हैं कि यह पुनर्स्थापित करने के लिए एक निर्माता कॉल करने के लिए चाहता है के बाद महत्व। लेकिन कौन जानता है, आपने लेख का उद्धरण नहीं दिया है या उद्धृत किया है जहां यह कन्स्ट्रक्टर चेनिंग का वर्णन करता है, इसलिए हो सकता है कि यह किसी अन्य असामान्य अर्थ में इसका उपयोग कर रहा हो, पहले से ही कहीं और वर्णित है। –

+1

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

+1

@Amardeep: सहमत है, यह कहना है कि निर्माता श्रृंखलन "असंभव" सी ++ 03 में, के बजाय "अवैध" है ज्यादा सही होगा। ऐसा करने के वर्णन के लिए बस कोई वाक्यविन्यास नहीं है। जैसा कि आप कहते हैं, एक कन्स्ट्रक्टर को बुलाए जाने वाली सामान्य परिभाषा द्वारा कन्स्ट्रक्टर चेनिंग जैसी ही चीज नहीं है। –

उत्तर

17

पैरा मूल रूप से कहना है कि यह:

class X 
{ 
    void Init(params) {/*common initing code here*/ } 
    X(params1) { Init(someParams); /*custom code*/ } 
    X(params2) { Init(someOtherParams); /*custom code*/ } 
}; 

आप एक सदस्य समारोह से एक निर्माता या तो फोन नहीं कर सकते हैं। यह आप पर लग सकता है कि आप इसे किया है, लेकिन है कि एक भ्रम है:

class X 
{ 
public: 
    X(int i):i(i){} 
    void f() 
    { 
     X(3); //this just creates a temprorary - doesn't call the ctor on this instance 
    } 
    int i; 
}; 

int main() 
{ 
    using std::cout; 
    X x(4); 
    cout << x.i << "\n"; //prints 4 
    x.f(); 
    cout << x.i << "\n"; //prints 4 again 
} 
+0

@ आर्मेन .. आपका मतलब है कि यह पहली बार 4 प्रिंट कर रहा है, यह वास्तव में कन्स्ट्रक्टर को बुला रहा है, और दूसरी बार जब यह 4 प्रिंट करता है, हालांकि मुझे लगता है कि मैंने कन्स्ट्रक्टर को कॉल करके परिणाम को महसूस किया है (फ़ंक्शन शून्य से एफ()), जो वास्तव में हो रहा है वह नहीं है .. !!! क्या यह ?? लेकिन मुझे उपर्युक्त कोड में आपकी पहली टिप्पणी नहीं मिली // यह सिर्फ एक अस्थायी बनाता है - इस उदाहरण पर ctor को कॉल नहीं करता है। क्या आप इसे थोड़ा और स्पष्ट रूप से समझा सकते हैं? – jsp99

+0

यह सी ++ 11 के साथ बदल गया है, http://stackoverflow.com/a/33275207/1915854 देखें –

3

टेक्स्ट यह नहीं कहता है। यह सुझाव है कि आपके कन्स्ट्रक्टर को एक सदस्य फ़ंक्शन कॉल करें जो सामान्य और कानूनी है। यह स्पष्ट रूप से फिर से ctor को कॉल करने और अपने ctor और रीसेट फ़ंक्शन के बीच डुप्लिकेट कोड से बचने के लिए है।

Foo::Foo() { 
    Init(); 
} 

void Foo::Reset() { 
    Init(); 
} 

void Foo::Init() { 
    // ... do stuff ... 
} 
+0

देखना यह सच है कि पाठ समारोह है कि सिफारिश करने नहीं बनाए गए हैं कन्स्ट्रक्टर को कॉल करें, हालांकि टेक्स्ट कहता है "आप अपने सदस्य समारोह से कन्स्ट्रक्टर को कॉल करने का प्रयास करने के लिए लुभाने का प्रयास कर सकते हैं। जैसा कि बताया गया है, सी ++ में कन्स्ट्रक्टर कॉल चेनिंग अवैध है।" यह पता चलता है विचारों के कुछ भ्रम की स्थिति के माध्यम से, लेखक ने सोचा कि कि "निर्माता कॉल चेनिंग" "आपके सदस्य समारोह से निर्माता को" के साथ कुछ है, लेख या यह कर नहीं की सिफारिश की जाती है चाहे। निश्चित रूप से, बस संपादन ddgy हो सकता है। –

+0

"क्योंकि आपके पास पहले से ही एक कन्स्ट्रक्टर है जो ऐसा करता है, आप अपने सदस्य समारोह से कन्स्ट्रक्टर को कॉल करने का प्रयास करने के लिए लुभाने वाले हो सकते हैं।" मैंने सोचा था कि इसका मतलब था कि एक सदस्य समारोह एक निर्माता से बचना चाहिए .. !! ??? – jsp99

+0

@ एपीपी: जरूरी नहीं। उदाहरण के लिए, 'Foo'' * यह = Foo() नामक कक्षा में, वस्तु को रीसेट करने का एक बिल्कुल उचित तरीका हो सकता है, यदि आवश्यक नहीं है तो सबसे अधिक कुशल। फिर फ़ंक्शन कन्स्ट्रक्टर को कॉल करता है, यह इसे 'इस' बनाने के लिए कॉल नहीं करता है। –

0

मुझे यकीन है कि अगर यह (एक सदस्य समारोह से एक निर्माता बुला) काम करते हैं या नहीं होगा नहीं कर रहा हूँ, लेकिन यह एक बुरा व्यवहार है। शुरुआती कोड को नए फ़ंक्शन में ले जाना तर्कसंगत तरीका है।

मूल रूप से कह रही है, निर्माता फोन न करें जब तक कि आप का निर्माण ...

+0

यह सिर्फ बुरा व्यवहार ... यह काम नहीं कर सकता नहीं है। – Johnsyweb

+0

मैं जॉन्सवेब से सहमत हूं। किसी अन्य से एक कन्स्ट्रक्टर को कॉल करना केवल इसके अंदर एक अस्थायी स्थानीय चर बना देगा और कन्स्ट्रक्टर बाहर निकलने के बाद इसे हटा देगा। 'इस' वस्तु का किसी भी से प्रभावित नहीं होता है। ऐसा करने का एकमात्र तरीका एक प्लेसमेंट नया है और सी ++ एफएक्यू ने बार-बार दोहराया है कि यह करने के लिए एक भयानक बात है। – MasterMastic

1

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

सदस्य कार्यों में रचनाकारों को कॉल करने का अच्छा अभ्यास नहीं है क्योंकि यह व्युत्पन्न प्रत्येक वर्ग की वस्तुओं को बनाता है।

15

सी ++ 11 कन्स्ट्रक्टर चेनिंग (आंशिक रूप से) की अनुमति देता है। इस सुविधा को "delegating constructors" कहा जाता है। तो सी ++ 11 में आप निम्नलिखित

class Foo 
{ 
public: 
    Foo(int a) : Foo() { _a = a; } 
    Foo(char* b) : Foo() { _b = b; } 
    Foo() { _c = 1.5; } 
private: 
    int _a = 0; 
    char* _b = nullptr; 
    double _c; 
}; 

कर सकते हैं हालांकि, वहाँ एक गंभीर सीमा यह है कि एक निर्माता है कि एक और निर्माता कॉल किसी अन्य सदस्य प्रारंभ करने की अनुमति नहीं है। तो तुम एक सौंपने के निर्माता के साथ निम्न कार्य नहीं कर सकते हैं:

class Foo 
{ 
public: 
    Foo(int a) : Foo(), _a(a) { } 
    Foo(char* b) : Foo(), _b(b) { } 
    Foo() { _c = 1.5; } 
private: 
    int _a = 0; 
    char* _b = nullptr; 
    double _c; 
}; 

MSVC++ 2013 देता संकलन त्रुटि "C3511: एक सौंपने के निर्माता के लिए एक कॉल केवल सदस्य-प्रारंभकर्ता होगा" बाद के कोड उदाहरण के लिए।

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