c++ - सुपरक्लास कन्स्ट्रक्टर को कॉल करने के नियम क्या हैं?




inheritance constructor (6)

उप-वर्ग से सुपरक्लास कन्स्ट्रक्टर को कॉल करने के लिए सी ++ नियम क्या हैं?

उदाहरण के लिए, मुझे जावा में पता है, आपको इसे सबक्लास कन्स्ट्रक्टर की पहली पंक्ति के रूप में करना होगा (और यदि आप नहीं करते हैं, तो नो-एर्ग सुपर कन्स्ट्रक्टर को एक निहित कॉल माना जाता है - यदि यह गायब है तो आपको संकलन त्रुटि दे रही है) ।


जब किसी वर्ग को कई कक्षाओं से प्राप्त होता है तो किसी ने कन्स्ट्रक्टर कॉल के अनुक्रम का उल्लेख नहीं किया है। वर्गों को प्राप्त करते समय अनुक्रम का उल्लेख किया गया है।


माता-पिता कन्स्ट्रक्टर को मान पास करने का एकमात्र तरीका प्रारंभिक सूची के माध्यम से होता है। Initilization सूची एक के साथ कार्यान्वित किया गया है: और उसके बाद कक्षाओं और मूल्यों की एक सूची उस वर्ग निर्माता को पारित किया जाना है।

Class2::Class2(string id) : Class1(id) {
....
}

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


यदि आपके बेस कंस्ट्रक्टर में डिफ़ॉल्ट पैरामीटर हैं तो बेस क्लास को स्वचालित रूप से कॉल किया जाएगा।

using namespace std;

class Base
{
    public:
    Base(int a=1) : _a(a) {}

    protected:
    int _a;
};

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

  void printit() { cout << _a << endl; }
};

int main()
{
   Derived d;
   d.printit();
   return 0;
}

आउटपुट है: 1


यदि उनके पास कोई तर्क नहीं है तो बेस क्लास कन्स्ट्रक्टर स्वचालित रूप से आपके लिए बुलाए जाते हैं। यदि आप किसी तर्क के साथ सुपरक्लस कन्स्ट्रक्टर को कॉल करना चाहते हैं, तो आपको उप-वर्ग की कन्स्ट्रक्टर प्रारंभिक सूची का उपयोग करना होगा। जावा के विपरीत, सी ++ एकाधिक विरासत (बेहतर या बदतर के लिए) का समर्थन करता है, इसलिए बेस क्लास को "सुपर ()" के बजाय नाम से संदर्भित किया जाना चाहिए।

class SuperClass
{
    public:

        SuperClass(int foo)
        {
            // do something with foo
        }
};

class SubClass : public SuperClass
{
    public:

        SubClass(int foo, int bar)
        : SuperClass(foo)    // Call the superclass constructor in the subclass' initialization list.
        {
            // do something with bar
        }
};

here और here कन्स्ट्रक्टर की प्रारंभिक सूची पर अधिक जानकारी।


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


class A : public B
{
public:
  A(int a, int b, int c);
private:
  int b_, c_;
};

फिर, मानते हुए कि बी में एक कन्स्ट्रक्टर है जो एक int लेता है, ए का कन्स्ट्रक्टर इस तरह दिख सकता है:


A::A(int a, int b, int c) 
  : B(a), b_(b), c_(c) // initialization list
{
  // do something
}

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

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


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

class Sub : public Base
{
  Sub(int x, int y)
  : Base(x), member(y)
  {
  }
  Type member;
};

यदि इस बिंदु पर चलने वाली कोई भी चीज़ फेंकता है, तो आधार / सदस्यों ने जो निर्माण पूरा कर लिया था, उनके विनाशकों को बुलाया गया है और अपवाद को कॉलर को पुनर्स्थापित किया गया है। यदि आप चेनिंग के दौरान अपवादों को पकड़ना चाहते हैं, तो आपको फ़ंक्शन का उपयोग करना होगा:

class Sub : public Base
{
  Sub(int x, int y)
  try : Base(x), member(y)
  {
    // function body goes here
  } catch(const ExceptionType &e) {
    throw kaboom();
  }
  Type member;
};

इस रूप में, ध्यान दें कि फ़ंक्शन ब्लॉक शरीर के अंदर होने के बजाय फ़ंक्शन का मुख्य भाग है; यह इसे निहित या स्पष्ट सदस्य और बेस क्लास प्रारंभिकताओं के साथ-साथ समारोह के शरीर के दौरान फेंकने वाले अपवादों को पकड़ने की अनुमति देता है। हालांकि, यदि फ़ंक्शन कैच ब्लॉक एक अलग अपवाद नहीं फेंकता है, तो रनटाइम मूल त्रुटि को फिर से चलाएगा; प्रारंभिकरण के दौरान अपवादों को अनदेखा नहीं किया जा सकता है।





constructor