2012-11-16 19 views
5

मैं एक हीरे की समस्या है जो इस तरह लग रहे है:परिसर हीरा मुद्दा: सी ++ आभासी विरासत

__ A 
/ |\ 
| B | \ 
v|/v v\|v \v 
B2 B3 C 
    \v /v /
    B4 /
    \ /
     D 

मैं कई तरह से कोई डुप्लिकेट प्राप्त करने के लिए सबसे अच्छा आभासी विरासत करने की कोशिश की, लेकिन मैं एक समाधान नहीं मिल सका। कक्षा ए में एक स्थिति है। यहां नमूना आउटपुट है:

Call: A() position pointer is: 0x2203be8 
Call: B() 
Call: B2() position pointer is: 0x2203be8 
Call: B3() position pointer is: 0x2203be8 
Call: C() position pointer is: 0x2203a28 
Call: B4() position pointer is: 0x2203be8 
Call: D() position pointer is: 0x2203a28 

डी और सी के पास स्थिति के लिए एक ही सूचक क्यों नहीं है? इस ए :: स्थिति के लिए कोई कन्स्ट्रक्टर क्यों नहीं है? इसे हल करने के लिए मुझे क्या आभासी विरासत बनाना चाहिए? धन्यवाद।

संपादित करें:

class A; 
class B; 
class B2 : public virtual B, public virtual A; 
class B3 : public virtual B, public virtual A; 
class C : public virtual A; 
class B4 : public virtual B2, public virtual B3; 
class D : public B4, public C; 

संपादित करें 2:

यहाँ एक कोड नमूना है

A::A() 
{ 
    std::cerr << "Call: A() position pointer is: " << &_position << std::endl; 
} 
+4

यह एक भयंकर दिखने वाला हीरा है। –

+0

डायमंड के भीतर डायमंड! –

+0

आपको वास्तविक विरासत संबंधों का उपयोग करने की आवश्यकता है जो आप उपयोग कर रहे हैं। एकल उत्तर में प्रारूप का उपयोग करने पर विचार करें (केवल 'derived_type: [virtual] आधार, [आभासी] base2 ...' प्रदान करें। यह समझाने में भी दिलचस्प होगा कि आप आउटपुट –

उत्तर

1

क्या कोड आप करते हैं: उत्पादन बनाने के लिए, मैं हर कंस्ट्रक्टर्स के अंदर इस कोड डाल वर्तमान में है? ऐसा लगता है कि समाधान होने जा रहा है:

class D; 
class C : public virtual D; 
class B4 : public virtual D; 
class B2 : public virtual B4; 
class B3 : public virtual B4; 
class B : public B2, public B3; 
class A : public B2, public B3, public C; 

आपके आरेख के आधार पर। यदि मैं गलत यह पढ़ रहा हूँ और एक आधार है, नहीं डी तो यह इस तरह दिखना करने की आवश्यकता होगी:

class A; 
class B; 
class B2 : public virtual B, public virtual A; 
class B3 : public virtual B, public virtual A; 
class C : public virtual A; 
class B4 : public virtual B2, public virtual B3; 
class D : public B4, public C; 
+0

ओह में "सीर" है! मुझे ए के लिए फिर से लिखने दो। – OmnipotentEntity

+1

इसे और अधिक स्पष्ट बनाने के लिए, आपके दूसरे सेट से वे 'वर्चुअल' गायब हैं, वे 'डी' पर हैं। –

+0

दूसरा अच्छा कोड –

0

क्यों करता है डी और सी स्थिति के लिए एक ही सूचक नहीं है?

क्योंकि आप बी 4 और सी से गैर-वर्चुअल रूप से विरासत में हैं। इसका मतलब है कि आपके पास ए (और दो पॉइंटर्स) की दो प्रतियां हैं।

डी निर्माता में & बी 4 :: स्थिति & सी :: स्थिति

क्यों इस एक :: स्थिति के लिए कोई निर्माता है से अलग है?

कोई विचार नहीं, आपके ए क्लास में एक से अधिक कन्स्ट्रक्टर हैं, और एक डिफ़ॉल्ट-मूक कन्स्ट्रक्टर को C :: C() द्वारा बुलाया जाता है?

इसे हल करने के लिए मुझे क्या आभासी विरासत बनाना चाहिए?

सभी वर्चुअल बनाएं। इसका मतलब है कि आपको प्रत्येक कन्स्ट्रक्टर को डी :: डी() (यानी ए :: ए(), बी :: बी(), बी 2 :: बी 2(), बी 3 :: बी 3(), सी :: से स्पष्ट रूप से कॉल करने की आवश्यकता है। सी())।

टीबी मुझे विश्वास है कि आपको अपने पदानुक्रम पर पुनर्विचार करना चाहिए। मुझे विवरण नहीं पता, लेकिन ऐसा लगता है कि आपकी समस्या घटक-डिजाइन के माध्यम से एक क्लीनर समाधान है।

+0

नहीं है, मेरे पास केवल ए के लिए एक कन्स्ट्रक्टर है और ऐसा लगता है कि स्थिति के लिए दूसरा पॉइंटर –

+1

प्रारंभ नहीं किया गया है, भले ही 'बी 4' और' सी 'गैर-वर्चुअल रूप से विरासत में प्राप्त हो, विरासत वस्तु साझा करेगी उनमें से दोनों के लिए एक 'ए'', क्योंकि वे दोनों 'ए' के ​​लिए वर्चुअल विरासत का उपयोग करते हैं। इससे कोई फर्क नहीं पड़ता कि कैसे 'डी 'विरासत में आता है।इसके अलावा 'डी' के लिए प्रत्येक कन्स्ट्रक्टर को स्पष्ट रूप से कॉल करने की आवश्यकता नहीं है। – bames53

4

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

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


मैं आपकी समस्या को पुन: पेश करने की कोशिश कर रहा हूं। यहाँ कोड मैं का उपयोग कर रहा है:

#include <iostream> 

struct A { int a; }; 
struct B { int b; }; 
struct B2 : virtual B, virtual A {}; 
struct B3 : virtual B, virtual A {}; 
struct B4 : virtual B2, virtual B3 {}; // these virtuals are unnecessary in this case... 
struct C : virtual A {}; 
struct D : B4, C {}; 

int main() { 
    D d; 
    std::cout << &((B4*)&d)->a << '\n'; 
    std::cout << &((B3*)(B4*)&d)->a << '\n'; 
    std::cout << &((B2*)(B4*)&d)->a << '\n'; 
    std::cout << &((A*)(B2*)(B4*)&d)->a << '\n'; 
    std::cout << &((A*)(B3*)(B4*)&d)->a << '\n'; 
    std::cout << &((C*)&d)->a << '\n'; 
    std::cout << &((A*)(C*)&d)->a << '\n'; 
} 

लेकिन परिणाम मैं उम्मीद के रूप में कर रहे हैं, जहां a सदस्य हर वस्तु के लिए एक ही है। मैं एक ही परिणाम प्राप्त अगर मैं पते के रूप में अच्छी तरह से कंस्ट्रक्टर्स में प्रिंट आउट का उपयोग करें: मैं एक मामूली बदलाव करते हैं http://ideone.com/8FdQ1O

और सी की परिभाषा से virtual कीवर्ड निकालने:

... 
struct C : A {}; 
... 

(version using constructors)

तब मुझे वह समस्या दिखाई देती है जहां आप वर्णन करते हैं कि सी के पास बी 2, बी 3 और बी 4 द्वारा उपयोग किए गए आभासी से अलग एक उप-वस्तु है।

क्या आप वाकई virtual कीवर्ड का उपयोग कर रहे सभी स्थानों में कीवर्ड का उपयोग कर रहे हैं? आपके द्वारा दिखाए गए परिणाम यह इंगित करते हैं कि आप इसे कहीं याद कर रहे हैं। साथ ही, मुझे लगता है कि आपके द्वारा दिखाया गया आउटपुट आपके द्वारा दिखाए गए कोड खंडों के रूप में रचनाकारों के समान क्रम को प्रतिबिंबित नहीं करता है; आउटपुट ए() पहले दिखाता है, लेकिन कोड इंगित करता है कि बी() को पहले निष्पादित किया जाना चाहिए।


तरह से आभासी विरासत काम करता है कि एक सबसे व्युत्पन्न प्रकार प्रत्येक प्रकार कि लगभग विरासत ट्री में कहीं विरासत में मिलती है के लिए एक एकल आभासी उप वस्तु में शामिल होंगे है। साथ ही सबसे व्युत्पन्न प्रकार गैर आभासी विरासत का प्रत्येक उदाहरण के लिए एक उप-वस्तु में शामिल होंगे:

struct A {}; 
struct B : virtual A {}; 
struct C : A, B {}; 
struct D : virtual A, C {}; 
struct E : A, D {}; 
struct F : virtual A, E {}; 
struct G : A, F {}; 

G g; 

g चार A उप वस्तुओं की कुल होता है; हर बार A के लिए एक गैर लगभग है (C, E, और G में), और एक बार बार A लगभग विरासत में मिला है सभी के लिए विरासत में मिला (B, D, और F में)।

+0

दुर्भाग्यवश, मैंने आवश्यक सभी वर्चुअल कीवर्ड जोड़े और मुझे अभी भी बग मिला। मैंने 4.6.3 –

+0

@GuillaumeRacicot का उपयोग किया है, क्या आप कह रहे हैं कि जब आपने प्रोग्राम चलाया तो मैंने आपको मुद्दा देखा? या आपने अपना कोड किसी भी तरह संशोधित किया है? किसी को भी समस्या का निदान करने के लिए आपको अपना वास्तविक कोड प्रदान करना होगा क्योंकि पहले से उपलब्ध टुकड़े में समस्या का कारण नहीं है। – bames53

+0

जो प्रोग्राम आपने मुझे भेजा है वह बिल्कुल वही था। समस्या यह है कि मेरे पास काम करने वाला एक ही कोड है ... –

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