multiple - parameterized constructor in c++




क्या मैं सी++ में किसी अन्य कन्स्ट्रक्टर(कन्स्ट्रक्टर चेनिंग) से कन्स्ट्रक्टर को कॉल कर सकता हूं? (10)

अगर मैं आपके प्रश्न को सही ढंग से समझता हूं, तो आप पूछ रहे हैं कि क्या आप सी ++ में कई रचनाकारों को कॉल कर सकते हैं?

यदि आप यही चाहते हैं, तो नहीं - यह संभव नहीं है।

आप निश्चित रूप से कई रचनाकार हो सकते हैं, प्रत्येक अद्वितीय तर्क हस्ताक्षर के साथ, और फिर जब आप एक नई वस्तु को तुरंत चालू करते हैं तो उसे कॉल करें।

आप अंत में डिफॉल्ट तर्क के साथ एक कन्स्ट्रक्टर भी प्राप्त कर सकते हैं।

लेकिन आपके पास एकाधिक कन्स्ट्रक्टर नहीं हो सकते हैं, और फिर उनमें से प्रत्येक को अलग से कॉल करें।

एक C# डेवलपर के रूप में मैं रचनाकारों के माध्यम से चलाने के लिए प्रयोग किया जाता है:

class Test {
    public Test() {
        DoSomething();
    }

    public Test(int count) : this() {
        DoSomethingWithCount(count);
    }

    public Test(int count, string name) : this(count) {
        DoSomethingWithName(name);
    }
}

क्या सी ++ में ऐसा करने का कोई तरीका है?

मैंने कक्षा के नाम को कॉल करने और 'यह' कीवर्ड का उपयोग करने की कोशिश की, लेकिन दोनों विफल हो गए।


एक और विकल्प जो अभी तक नहीं दिखाया गया है, वह है कि आप जिस वर्ग को ढूंढ रहे हैं उसे प्राप्त करने के लिए अपनी कक्षा को अपनी मूल कक्षा के चारों ओर एक हल्के इंटरफ़ेस कक्षा को लपेटना है:

class Test_Base {
    public Test_Base() {
        DoSomething();
    }
};

class Test : public Test_Base {
    public Test() : Test_Base() {
    }

    public Test(int count) : Test_Base() {
        DoSomethingWithCount(count);
    }
};

यह गन्दा हो सकता है यदि आपके पास कई रचनाकार हैं जिन्हें अपने "अगले स्तर पर" समकक्ष को कॉल करना होगा, लेकिन कुछ हद तक रचनाकारों के लिए, यह काम करने योग्य होना चाहिए।


नहीं, आप सी ++ 03 में एक कन्स्ट्रक्टर को दूसरे से कॉल नहीं कर सकते (जिसे एक प्रतिनिधि कन्स्ट्रक्टर कहा जाता है)।

यह सी ++ 11 (उर्फ सी ++ 0x) में बदल गया, जिसने निम्नलिखित वाक्यविन्यास के लिए समर्थन जोड़ा:
( Wikipedia से लिया गया उदाहरण)

class SomeType
{
  int number;

public:
  SomeType(int newNumber) : number(newNumber) {}
  SomeType() : SomeType(42) {}
};

नहीं, सी ++ में आप एक कन्स्ट्रक्टर से कन्स्ट्रक्टर को कॉल नहीं कर सकते हैं। वॉरेन ने बताया कि आप क्या कर सकते हैं, यह है:

  • विभिन्न हस्ताक्षरों का उपयोग करके, कन्स्ट्रक्टर को अधिभारित करें
  • एक "सरल" संस्करण उपलब्ध कराने के लिए, तर्कों पर डिफ़ॉल्ट मानों का उपयोग करें

ध्यान दें कि पहले मामले में, आप एक कन्स्ट्रक्टर को दूसरे से कॉल करके कोड डुप्लिकेशन को कम नहीं कर सकते हैं। आप निश्चित रूप से एक अलग, निजी / संरक्षित, विधि कर सकते हैं जो सभी प्रारंभिक कार्य करता है, और निर्माता को मुख्य रूप से तर्क प्रबंधन से निपटने दें।


मेरा मानना ​​है कि आप एक निर्माता से कन्स्ट्रक्टर को कॉल कर सकते हैं। यह संकलित और चलाएगा। मैंने हाल ही में किसी को यह देखा और यह विंडोज और लिनक्स दोनों पर चला।

यह सिर्फ वही नहीं करता जो आप चाहते हैं। आंतरिक कन्स्ट्रक्टर एक अस्थायी स्थानीय ऑब्जेक्ट का निर्माण करेगा जो बाहरी कन्स्ट्रक्टर रिटर्न के बाद हटा दिया जाता है। उन्हें अलग-अलग रचनाकार भी होना चाहिए या आप एक रिकर्सिव कॉल तैयार करेंगे।

रेफरी: https://isocpp.org/wiki/faq/ctors#init-methods


मैं एक private friend विधि के उपयोग का प्रस्ताव दूंगा जो कि कन्स्ट्रक्टर के अनुप्रयोग तर्क लागू करता है और विभिन्न रचनाकारों द्वारा इसे बुलाया जाता है। यहाँ एक उदाहरण है:

मान लें कि हमारे पास कुछ निजी फ़ील्ड के साथ StreamArrayReader नामक एक कक्षा है:

private:
    istream * in;
      // More private fields

और हम दो रचनाकारों को परिभाषित करना चाहते हैं:

public:
    StreamArrayReader(istream * in_stream);
    StreamArrayReader(char * filepath);
    // More constructors...

जहां दूसरा व्यक्ति केवल पहले का उपयोग करता है (और निश्चित रूप से हम पूर्व के कार्यान्वयन को डुप्लिकेट नहीं करना चाहते हैं)। आदर्श रूप से, कोई ऐसा कुछ करना चाहेगा:

StreamArrayReader::StreamArrayReader(istream * in_stream){
    // Implementation
}

StreamArrayReader::StreamArrayReader(char * filepath) {
    ifstream instream;
    instream.open(filepath);
    StreamArrayReader(&instream);
    instream.close();
}

हालांकि, सी ++ में इसकी अनुमति नहीं है। इसी कारण से, हम एक निजी मित्र विधि को निम्नानुसार परिभाषित कर सकते हैं जो कि पहले कन्स्ट्रक्टर को क्या करना चाहिए लागू करता है:

private:
  friend void init_stream_array_reader(StreamArrayReader *o, istream * is);

अब यह विधि (क्योंकि यह एक दोस्त है) o के निजी क्षेत्रों तक पहुंच है। फिर, पहला कन्स्ट्रक्टर बन जाता है:

StreamArrayReader::StreamArrayReader(istream * is) {
    init_stream_array_reader(this, is);
}

ध्यान दें कि यह नव निर्मित प्रतियों के लिए कई प्रतियां नहीं बनाता है। दूसरा वाला बन जाता है:

StreamArrayReader::StreamArrayReader(char * filepath) {
    ifstream instream;
    instream.open(filepath);
    init_stream_array_reader(this, &instream);
    instream.close();
}

यही है, एक कन्स्ट्रक्टर को दूसरे फोन करने के बजाय, दोनों एक निजी दोस्त को बुलाओ!


यह दृष्टिकोण कुछ प्रकार के वर्गों के लिए काम कर सकता है (जब असाइनमेंट ऑपरेटर 'अच्छी तरह से' व्यवहार करता है):

Foo::Foo()
{
    // do what every Foo is needing
    ...
}

Foo::Foo(char x)
{
    *this = Foo();

    // do the special things for a Foo with char
    ...
}

यह ध्यान देने योग्य है कि आप अपने कन्स्ट्रक्टर में अभिभावक वर्ग के निर्माता को कॉल कर सकते हैं जैसे:

class A { /* ... */ };

class B : public A
{
    B() : A()
    {
        // ...
    }
};

लेकिन, नहीं, आप एक ही कक्षा के दूसरे निर्माता को नहीं बुला सकते हैं।


सीधे शब्दों में कहें, आप सी ++ 11 से पहले नहीं कर सकते हैं।

सी ++ 11 प्रतिनिधियों को प्रस्तुत करने का परिचय देता है:

प्रतिनिधि कन्स्ट्रक्टर

यदि वर्ग प्रारंभकर्ता सूची में वर्ग का नाम वर्ग-या-पहचानकर्ता के रूप में प्रकट होता है, तो सूची में केवल उस सदस्य प्रारंभकर्ता को शामिल होना चाहिए; ऐसे कन्स्ट्रक्टर को प्रतिनिधि कन्स्ट्रक्टर के रूप में जाना जाता है, और प्रारंभकर्ता सूची के एकमात्र सदस्य द्वारा चयनित कन्स्ट्रक्टर लक्ष्य कन्स्ट्रक्टर है

इस मामले में, लक्ष्य कन्स्ट्रक्टर को ओवरलोड रिज़ॉल्यूशन द्वारा चुना जाता है और पहले निष्पादित किया जाता है, फिर नियंत्रण प्रतिनिधि को वापस लेता है और उसके शरीर को निष्पादित किया जाता है।

प्रतिनिधि रचनाकार रिकर्सिव नहीं हो सकते हैं।

class Foo {
public: 
  Foo(char x, int y) {}
  Foo(int y) : Foo('a', y) {} // Foo(int) delegates to Foo(char,int)
};

ध्यान दें कि एक प्रतिनिधि कन्स्ट्रक्टर एक सब कुछ या कुछ भी प्रस्ताव नहीं है; यदि कोई कन्स्ट्रक्टर किसी अन्य निर्माता को प्रतिनिधि करता है, तो कॉलिंग कन्स्ट्रक्टर को इसकी प्रारंभिक सूची में कोई अन्य सदस्य होने की अनुमति नहीं है। यह समझ में आता है अगर आप एक बार कॉन्स / संदर्भ सदस्यों को शुरू करने के बारे में सोचते हैं, और केवल एक बार।


C++11 , एक Wikipedia :

class Foo  {
     int d;         
public:
    Foo  (int i) : d(i) {}
    Foo  () : Foo(42) {} //New to C++11
};

इसके अतिरिक्त, सदस्यों को भी इस तरह शुरू किया जा सकता है।

class Foo  {
     int d = 5;         
public:
    Foo  (int i) : d(i) {}
};

यह प्रारंभिक सहायक विधि बनाने की आवश्यकता को खत्म करना चाहिए। और अभी भी अनुशंसा की जा रही है कि किसी भी सदस्य का उपयोग करने से बचने के लिए रचनाकारों या विनाशकों में किसी वर्चुअल फ़ंक्शन को कॉल न करें।





constructor