2009-01-19 24 views
7

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

एक ---> बी ---> डी

\ ---> सी ------^

उत्तर

3

यह एक सही समस्या के लिए समाधान है?

"डायमंड" विरासत समस्याग्रस्त है, और समाधान के सही स्पष्टीकरण समझाने का एक सा लगता है। मैं सुझाव है कि आप मेयर्स 'प्रभावी सी ++ की निम्नलिखित अध्यायों पढ़ें:

  • मद 26, गार्ड संभावित अस्पष्टता
  • मद 43, एकाधिक वंशानुक्रम विवेकपूर्ण तरीके सेउपयोग के खिलाफ।
19

... ध्यान दें, हर्ब Sutter एकाधिक वंशानुक्रम (1) here, (2) here और (3) here बारे में लिखा था 3 उत्कृष्ट लेख। उन्होंने गुरु-ऑफ-द-हफ्ते here में उपयोगी लेखों का एक और समूह लिखा। अत्यधिक अनुशंसित ...

सबसे पहले, मुझे यकीन नहीं है कि मुझे आपकी पदानुक्रम सही हो। मैं इसे ले यह इस तरह है:

struct A { 
    virtual void F() = 0; 
}; 

struct B : A { void F() { } }; 
struct C : A { }; 
struct D : B, C { }; 

खैर, डी, सार है क्योंकि वहाँ प्रकार डी की एक वस्तु में दो A subobjects हैं: एक यह है कि बी के जाली के माध्यम से B द्वारा ठोस बना है, और एक है कि C के माध्यम से जाली जाली में अभी भी सार है। मुझे लगता है कि आपके पास D पर पॉइंटर है और F पर कॉल करने का प्रयास करें। हाँ, एक अस्पष्टता उठता है, क्योंकि संकलक दो अलग-अलग lattices में दो कार्य F पाता है:

D -> B::F 
D -> C -> A::F 

इस तरह देख रहे हैं:

F() F() 
    A  A 
    |  | 
F() B  C 
     \ /
     D 

आप एक लगभग से पाने से उस स्थिति को औपचारिक रूप से ठीक कर सकते हैं:

struct B : virtual A { void F() { } }; 
struct C : virtual A { }; 
struct D : B, C { }; 

आपके पास यह स्थिति है, जिसे हीरा विरासत कहा जाता है:

 F() 
     A 
    / \ 
F() B  C 
     \ /
     D 

और लुकअप करने पर, यह पाया जाता है कि B::FA::F ओवरराइडिंग है। हालांकि A::F अभी भी D::C::A के माध्यम से पहुंचा जा सकता है, यह अब अस्पष्टता नहीं है, क्योंकि A विरासत में मिला था।

चाहे यह आपकी विशेष समस्या में सही समाधान है - निश्चित रूप से यह निश्चित नहीं है। कक्षा से वर्चुअल प्राप्त करने से अक्सर बेहतर तरीके होते हैं। आभासी फ़ंक्शन टेबलों के विलय के बारे में आपके प्रश्न के लिए - यह पूरी तरह कार्यान्वयन के आधार पर है। GCC, जहां तक ​​मुझे पता है, अगर हम आभासी प्राप्त करते हैं, तो D की आभासी तालिका में एक उदाहरण के लिए एक सूचक रखें।

+0

धन्यवाद। मैंने यही पूछा है। यदि कार्यक्षमता संकलक-कार्यान्वयन-निर्भर है तो इसे जाने का कोई तरीका नहीं है। –

+0

व्यवहार हर कंपाइलर के लिए समान है - यह तरीका है कि कंप्यूटर्स इसे अलग करते हैं। आप संकलक पर भरोसा कर सकते हैं कि वे एक-दूसरे की तरह व्यवहार करते हैं, जब तक कि आप वस्तु के किसी विशेष लेआउट (जैसे आकार का मूल्य) पर निर्भर न हों, जो कार्यान्वयन पर निर्भर करेगा। –

+0

ठीक है, मुझे और अधिक सटीक पूछने दें: यदि हीरा वर्चुअल विरासत है और ए और बी दोनों में परिभाषित एक फ़ंक्शन है, लेकिन सी में नहीं, तो क्या मैं डी के माध्यम से फ़ंक्शन तक पहुंच सकता हूं? और वह कौन सा होगा, जिसे ए में परिभाषित किया गया है या बी से एक? क्या व्यवहार सभी कंपाइलरों के लिए संगत है? –

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