2013-04-03 9 views
19
#include <iostream> 
#include <stdio.h> 
using namespace std; 

// Base class 
class Shape 
{ 
    public: 
     void setWidth(int w) 
     { 
     width = w; 
     } 
     void setHeight(int h) 
     { 
     height = h; 
     } 
     Shape() 
     { 
    printf("creating shape \n"); 
     } 
     Shape(int h,int w) 
     { 
    height = h; 
     width = w; 
     printf("creatig shape with attributes\n"); 
     } 
    protected: 
     int width; 
     int height; 
}; 

// Derived class 
class Rectangle: public Shape 
{ 
    public: 
     int getArea() 
     { 
     return (width * height); 
     } 
     Rectangle() 
     { 
    printf("creating rectangle \n"); 
     } 
     Rectangle(int h,int w) 
     { 
    printf("creating rectangle with attributes \n"); 
    height = h; 
     width = w; 
     } 
}; 

int main(void) 
{ 
    Rectangle Rect; 

    Rect.setWidth(5); 
    Rect.setHeight(7); 

    Rectangle *square = new Rectangle(5,5); 
    // Print the area of the object. 
    cout << "Total area: " << Rect.getArea() << endl; 

    return 0; 
} 

कार्यक्रम के उत्पादन में नीचेसी ++ बुला आधार वर्ग कंस्ट्रक्टर्स

creating shape 
creating rectangle 
creating shape 
creating rectangle with attributes 
Total area: 35 

दिया जाता है का निर्माण दोनों व्युत्पन्न वर्ग वस्तुओं मैं देख रहा हूँ यह हमेशा डिफ़ॉल्ट आधार वर्ग निर्माता called.Is है इसके लिए एक कारण है? और क्या यही कारण है कि पाइथन जैसी भाषाएं सी ++ जैसी निहित कॉल की बजाय बेस क्लास कन्स्ट्रक्टर की स्पष्ट कॉल पर जोर देती हैं?

+2

विरासत पदानुक्रम में प्रत्येक कन्स्ट्रक्टर को बेस -> व्युत्पन्न क्रम में बुलाया जाता है। विनाशकों को रिवर्स ऑर्डर में बुलाया जाता है। –

+0

मेरा सवाल है "क्या यह हमेशा बेस क्लास का डिफ़ॉल्ट कन्स्ट्रक्टर है जिसे बुलाया जाता है?" – liv2hak

+0

@ liv2hak लेकिन मुझे ऐसा लगता है कि 'आयताकार (int एच, int w) 'कन्स्ट्रक्टर दूसरे आयताकार init पर कॉल किया जाता है ... – Kupto

उत्तर

47

इसका संक्षिप्त उत्तर यह है, "क्योंकि सी ++ मानक यही निर्दिष्ट करता है"।

ध्यान दें कि आप हमेशा एक निर्माता है कि डिफ़ॉल्ट से भिन्न है, इसलिए की तरह है निर्दिष्ट कर सकते हैं:

class Shape { 

    Shape() {...} //default constructor 
    Shape(int h, int w) {....} //some custom constructor 


}; 

class Rectangle : public Shape { 
    Rectangle(int h, int w) : Shape(h, w) {...} //you can specify which base class constructor to call 

} 

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

4

जब ऑब्जेक्ट्स का निर्माण होता है, तो यह हमेशा बेस क्लास सबोबजेक्ट का निर्माण होता है, इसलिए बेस क्लास कन्स्ट्रक्टर को पहले कॉल किया जाता है, फिर व्युत्पन्न क्लास कन्स्ट्रक्टर को कॉल करें। इसका कारण यह है कि व्युत्पन्न वर्ग वस्तुओं में बेस क्लास से वंचित उप-तत्व होते हैं। बेस क्लास सबोबजेक्ट्स को प्रारंभ करने के लिए आपको हमेशा बेस क्लास कन्स्ट्रक्टर को कॉल करने की आवश्यकता होती है। हम आमतौर पर व्युत्पन्न वर्ग के सदस्य प्रारंभिक सूची पर बेस क्लास कन्स्ट्रक्टर को कॉल करते हैं। यदि आप बेस क्लास कन्स्ट्रक्टर को स्पष्ट रूप से कॉल नहीं करते हैं, तो संकलन बेस क्लास सबोबजेक्ट को आरंभ करने के लिए बेस क्लास के डिफ़ॉल्ट कन्स्ट्रक्टर को कॉल करेगा। हालांकि, डिफ़ॉल्ट कन्स्ट्रक्टर पर निहित कॉल हर समय आवश्यक काम नहीं करता है (उदाहरण के लिए, यदि बेस क्लास एक कन्स्ट्रक्टर को परिभाषित करता है जिसे बिना तर्क के कहा जा सकता है)।

जब ऑब्जेक्ट दायरे से बाहर होते हैं, तो यह पहले व्युत्पन्न वर्ग के विनाशक को कॉल करेगा, फिर बेस क्लास के विनाशक को कॉल करेगा।

+0

" यह हमेशा काम नहीं करेगा "से आपका क्या मतलब है? – liv2hak

+1

@ liv2hak यदि आपकी बेस क्लास एक कन्स्ट्रक्टर को परिभाषित करती है जिसे तर्क के बिना बुलाया जा सकता है, इस मामले में, कंपाइलर आपके लिए एक डिफ़ॉल्ट कन्स्ट्रक्टर उत्पन्न नहीं करता है, इसलिए, कंपाइलर आपके लिए बेस क्लास सबोबजेक्ट्स को प्रारंभ करने में सक्षम नहीं होगा, जो होगा त्रुटियों में परिणाम। इसलिए यह हर समय काम नहीं करता है। – taocp

11

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

Rectangle(int h,int w): 
    Shape(h,w) 
    {...} 

अन्य बेस क्लास कन्स्ट्रक्टर को कॉल करेगा।

0

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

1

सी ++ में, कंपाइलर हमेशा यह सुनिश्चित करता है कि ऑब्जेक्ट पदानुक्रम में कार्य सफलतापूर्वक कहा जाता है। ये कार्य रचनाकार और विनाशक हैं और वस्तु पदानुक्रम का मतलब विरासत का पेड़ है।

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

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

0

बेस क्लास का डिफ़ॉल्ट कन्स्ट्रक्टर क्यों कहा जाता है? बाहर निकलता है यह हमेशा मामला नहीं है। आधार वर्ग (विभिन्न हस्ताक्षरों के साथ) के किसी भी निर्माता को व्युत्पन्न वर्ग 'कन्स्ट्रक्टर से बुलाया जा सकता है। आपके मामले में, डिफ़ॉल्ट कन्स्ट्रक्टर को कॉल किया जाता है क्योंकि इसमें कोई पैरामीटर नहीं है, इसलिए यह डिफ़ॉल्ट है।

जब कोई व्युत्पन्न वर्ग बनाया जाता है, तो रचनाकारों को आदेश दिया जाता है हमेशा आधार -> पदानुक्रम में व्युत्पन्न होता है। अगर हमने:

class A {..} 
class B : A {...} 
class C : B {...} 
C c; 

जब ग बनाने की है, एक के लिए निर्माता पहले बी के लिए निर्माता, और फिर सी

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

Derived() : Base(5) 
{  
} 

तो ऐसी कोई निर्माता व्युत्पन्न वर्ग की initialisation सूची में लागू करने का कोई भी पैरामीटर के साथ निर्माता 'निर्माता, तो कार्यक्रम के एक आधार वर्ग मानता है'। यही कारण है कि कोई पैरामीटर (यानि डिफॉल्ट कन्स्ट्रक्टर) के साथ एक कन्स्ट्रक्टर का आह्वान किया जाता है।

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