2010-01-24 11 views
19

समस्या:C++ आभासी विरासत

class Base { 
public: 
    Base(Base* pParent); 
    /* implements basic stuff */ 
}; 

class A : virtual public Base { 
public: 
    A(A* pParent) : Base(pParent) {} 
    /* ... */ 
}; 

class B : virtual public Base { 
public: 
    B(B* pParent) : Base(pParent) {} 
    /* ... */ 
}; 

class C : public A, public B { 
public: 
    C(C* pParent) : A(pParent), B(pParent) {} // - Compilation error here 
    /* ... */ 
}; 

स्थान दिया पर, जीसीसी शिकायत है कि यह बेस समारोह कॉल(), अर्थात डिफ़ॉल्ट निर्माता से मेल नहीं कर सकते हैं। लेकिन सी बेस से सीधे प्राप्त नहीं होता है, केवल ए और बी के माध्यम से, तो जीसीसी यहां शिकायत क्यों करता है?

विचार? टीआईए /रोब

+0

संकलन नहीं RTTI सेट के साथ किया जाता है, हो सकता है? – Robert

+6

नहीं, विरासत एक संकलित समय की बात है, आरटीटीआई की आवश्यकता नहीं होगी। – GManNickG

उत्तर

43

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

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

ध्यान दें कि वर्चुअल बेस पहचानकर्ता को कन्स्ट्रक्टर की प्रारंभिक सूची में उपयोग करने की अनुमति है भले ही यह प्रश्न में कक्षा का प्रत्यक्ष आधार न हो।

+0

+1, सबसे सटीक उत्तर :) –

+0

अनुपूरक: ध्यान दें कि एक अमूर्त वर्ग कभी भी अपने आभासी आधार को प्रारंभ नहीं कर सकता है, इस प्रकार वर्चुअल बेस को ctor को अपने ctors init-list में कॉल करने की आवश्यकता नहीं है, भले ही कोई डिफ़ॉल्ट-ctor मौजूद न हो। – Deduplicator

+0

तो इसका मतलब है कि ए और बी अभिभावक वर्ग (यानी ': आधार (पीपीरेंट)' का प्रारंभिकरण) दोनों व्युत्पन्न कक्षा का निर्माण करते समय अनदेखा कर रहे हैं? – Chris

5

यदि आप कस्टम कन्स्ट्रक्टर घोषित करते हैं, तो डिफ़ॉल्ट कन्स्ट्रक्टर अक्षम है। आभासी विरासत में आप क्योंकि अन्यथा यह पता नहीं होता A, B द्वारा या द्वारा प्रारंभ करने के लिए कि क्या

7

आप स्पष्ट रूप से सी से बेस के लिए निर्माता को फोन करने की जरूरत है: एक समस्या

class C : public A, public B { 
public: 
C(C* pParent) : Base(pParent), A(pParent), B(pParent) {} 
/*... */ 
}; 
+0

मुझे नहीं पता था कि आप यह कर सकते हैं। क्या इसका मतलब यह है कि संकलक 'ए' और 'बी' के c'tors में कोड को अनदेखा करता है जहां वे 'बेस' शुरू करने लगते हैं? – quamrana

+1

कोई भी नहीं _can_ आप यह करते हैं, आप _must_ इसे करते हैं। कोई कोड अनदेखा नहीं किया जा रहा है। 'बेस' के लिए कन्स्ट्रक्टर को केवल एक बार बुलाया जाएगा, फिर ए और बी के लिए कन्स्ट्रक्टर का बॉडी, फिर सी – BenG

+0

के लिए कन्स्ट्रक्टर का बॉडी अब मैं कन्स्ट्रक्टर कॉल के आदेश और इसके पीछे कारणों को समझता हूं, सिवाय इसके कि मैं आमतौर पर केवल एक डिफ़ॉल्ट श्रेणी वाला बेस क्लास होता है, इसलिए मुझे 'बेस() 'के लिए स्पष्ट कॉल नहीं करना पड़ता है। निश्चित रूप से, ओपी के उदाहरण में, कंपाइलर्स को प्रोग्रामर संकेतों को अभी भी अनदेखा करना चाहिए कि 'बेस (पीपीरेंट)' को 'ए' और 'बी' दोनों के सीटर्स से सीधे बुलाया जाना चाहिए? – quamrana

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