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




parameterized constructor in c++ (12)

यदि आप बुरा होना चाहते हैं, तो आप इन-प्लेस "नया" ऑपरेटर का उपयोग कर सकते हैं:

class Foo() {
    Foo() { /* default constructor deliciousness */ }
    Foo(Bar myParam) {
      new (this) Foo();
      /* bar your param all night long */
    } 
};

लगता है मेरे लिए काम करता है।

संपादित करें

@ElvedinHamzagic बताते हैं, अगर फू में एक ऑब्जेक्ट होता है जो स्मृति आवंटित करता है, तो उस ऑब्जेक्ट को मुक्त नहीं किया जा सकता है। यह चीजों को और जटिल करता है।

एक और सामान्य उदाहरण:

class Foo() {
private:
  std::vector<int> Stuff;
public:
    Foo()
      : Stuff(42)
    {
      /* default constructor deliciousness */
    }

    Foo(Bar myParam)
    {
      this->~Foo();
      new (this) Foo();
      /* bar your param all night long */
    } 
};

निश्चित रूप से, थोड़ा कम सुरुचिपूर्ण लग रहा है। @ जॉनआईडोल का समाधान बहुत बेहतर है।

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

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

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

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

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

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


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

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

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

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

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

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

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

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


विजुअल सी ++ में आप कन्स्ट्रक्टर के अंदर इस नोटेशन का भी उपयोग कर सकते हैं: यह-> क्लासनाम :: क्लासनाम (दूसरे कन्स्ट्रक्टर के पैरामीटर)। नीचे एक उदाहरण देखें:

class Vertex
{
 private:
  int x, y;
 public:
  Vertex(int xCoo, int yCoo): x(xCoo), y(yCoo) {}
  Vertex()
  {
   this->Vertex::Vertex(-1, -1);
  }
};

मुझे नहीं पता कि यह कहीं और काम करता है, मैंने केवल विज़ुअल सी ++ 2003 और 2008 में इसका परीक्षण किया। आप जावा और सी # की तरह, मुझे लगता है कि कई रचनाकारों को भी इस तरह से कॉल कर सकते हैं।

पीएस: वाकई, मुझे आश्चर्य हुआ कि इससे पहले उल्लेख नहीं किया गया था।


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) {}
};

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


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

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

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

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

सी ++ 11: हाँ!

सी ++ 11 और बाद में यह वही सुविधा है (जिसे कंटेंटिंग कन्स्ट्रक्टर कहा जाता है)।

वाक्यविन्यास सी # से थोड़ा अलग है:

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

सी ++ 03: नहीं

दुर्भाग्य से, C ++ 03 में ऐसा करने का कोई तरीका नहीं है, लेकिन इसे अनुकरण करने के दो तरीके हैं:

  1. आप डिफ़ॉल्ट पैरामीटर के माध्यम से दो (या अधिक) कन्स्ट्रक्टर को जोड़ सकते हैं:

    class Foo {
    public:
      Foo(char x, int y=0);  // combines two constructors (char) and (char, int)
      // ...
    };
    
  2. सामान्य कोड साझा करने के लिए एक init विधि का उपयोग करें:

    class Foo {
    public:
      Foo(char x);
      Foo(char x, int y);
      // ...
    private:
      void init(char x, int y);
    };
    
    Foo::Foo(char x)
    {
      init(x, int(x) + 7);
      // ...
    }
    
    Foo::Foo(char x, int y)
    {
      init(x, y);
      // ...
    }
    
    void Foo::init(char x, int y)
    {
      // ...
    }
    

संदर्भ के लिए सी ++ एफएक्यू एंट्री देखें।


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

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

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


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

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

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

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

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


निर्णय लेने से परीक्षण करना अधिक आसान होगा :) इसे आजमाएं:

#include <iostream>

class A {
public:
    A( int a) : m_a(a) {
        std::cout << "A::Ctor" << std::endl;    
    }
    ~A() {
        std::cout << "A::dtor" << std::endl;    
    }
public:
    int m_a;
};

class B : public A {
public:
    B( int a, int b) : m_b(b), A(a) {}
public:
    int m_b;
};

int main() {
    B b(9, 6);
    std::cout << "Test constructor delegation a = " << b.m_a << "; b = " << b.m_b << std::endl;    
    return 0;
}

और इसे 98 std: g ++ main.cpp -std = c ++ 98 -o test_1 के साथ संकलित करें

तुम देखोगे:

A::Ctor
Test constructor delegation a = 9; b = 6
A::dtor

इसलिए :)


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

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

class SomeType
{
  int number;

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

एक कन्स्ट्रक्टर को कॉल करते समय यह वास्तव में ढेर या ढेर से स्मृति आवंटित करता है। तो एक और कन्स्ट्रक्टर में एक कन्स्ट्रक्टर को बुलाकर एक स्थानीय प्रतिलिपि बनाता है। तो हम एक और वस्तु को संशोधित कर रहे हैं, न कि जिस पर हम ध्यान केंद्रित कर रहे हैं।


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

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

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





constructor