2010-08-17 21 views
7

$ 4.11/2 राज्यों -सूचक

जहां B एक वर्ग प्रकार है "प्रकार के B के सदस्य सीवीT, सूचक" प्रकार का एक rvalue, एक करने के लिए परिवर्तित किया जा सकता प्रकार के rvalue जहां D एक व्युत्पन्न वर्ग B (10 अनुच्छेद) है "प्रकार सीवीT, की D के सदस्य के लिए सूचक"। यदि B एक दुर्गम (खंड 11), अस्पष्ट (10.2) या आभासी D, एक प्रोग्राम है जो इस रूपांतरण जरूरी की (10.1) आधार वर्ग है बीमार का गठन है।

मेरा प्रश्न कारण है कि हम में से BD का एक आभासी आधार वर्ग नहीं किया जा रहा से प्रतिबंधित भी है?

उत्तर

5

एक स्थिति पर विचार के लिए एक गैर आभासी आधार वर्ग को शामिल:

+-------------+ 
| A: int a; | 
+-------------+ 
| B: int b; | 
+-------------+ 
| A: int a; | 
+-------------+ 
| C: int c; | 
+-------------+ 
| D: int d; | 
+-------------+ 

D समाप्त होता है:

class A { int a; } 
class B : public A { int b; } 
class C : public A { int c; } 
class D : public B, public C { int d; } 

यहाँ एक संभव स्मृति लेआउट है यह वही है मैं विषय से संबंधित मिल सकता है दो A सबोबजेक्ट्स के साथ, क्योंकि यह B और C से प्राप्त होता है और दोनों में A सबोबजेक्ट होता है।

सदस्य चर के पॉइंटर्स आमतौर पर ऑब्जेक्ट की शुरुआत से पूर्णांक ऑफसेट के रूप में कार्यान्वित किए जाते हैं। इस मामले में, int a के लिए A ऑब्जेक्ट में पूर्णांक ऑफसेट शून्य है। तो A के int a के सूचक "शून्य के पूर्णांक ऑफसेट हो सकते हैं।

एक करने के लिए "प्रकार A की int a सूचक" एक परिवर्तित करने के लिए "प्रकार B की int a सूचक," तुम सिर्फ एक पूर्णांक A subobject B में स्थित (प्रथम A subobject) करने के लिए ऑफसेट की जरूरत है।

एक करने के लिए "प्रकार A की int a सूचक" एक परिवर्तित करने के लिए "प्रकार C की int a सूचक," तुम सिर्फ एक पूर्णांक A subobject C में स्थित (दूसरा A subobject) करने के लिए ऑफसेट की जरूरत है।

के बाद से संकलक जानता है, जहां B और CA के सापेक्ष है, संकलक कैसे A से B या C को खिन्न करने पर पर्याप्त जानकारी नहीं है।

अब एक स्थिति एक आभासी आधार वर्ग को शामिल करने पर विचार:

struct A { int a; } 
struct B : virtual public A { int b; } 
struct C : virtual public A { int c; } 
struct D : public B, public C { int d; } 

संभव स्मृति लेआउट:

+-------------+ 
| B: ptr to A | ---+ 
| int b; | | 
+-------------+ | 
| C: ptr to A | ---+ 
| int c; | | 
+-------------+ | 
| D: int d; | | 
+-------------+ | 
| A: int a; | <--+ 
+-------------+ 

आभासी आधार वर्ग आम तौर पर B और C (जो वस्तुतः A से निकाले जाते हैं) होने से लागू किया जाता है एक A subjobject के लिए एक सूचक शामिल है। A सबोबजेक्ट के पॉइंटर्स की आवश्यकता है क्योंकि का स्थान B और C के सापेक्ष स्थिर नहीं है।

यदि सब हम था एक था "प्रकार A की int a सूचक," हम, "प्रकार B की int a सूचक" एक करने के लिए इसे कास्ट करने के लिए B और C subobjects के स्थान के बाद से भिन्न हो सकते हैं सक्षम नहीं होगा A के सापेक्ष। A में B और न ही C पर बैक-पॉइंटर्स नहीं हैं, इसलिए हमारे पास काम करने के लिए डाउनकास्ट के लिए पर्याप्त जानकारी नहीं है।

+0

+1 – Bill

1

गैर-वर्चुअल विरासत के साथ, बेस-क्लास और व्युत्पन्न-वर्ग के सदस्यों को बेस क्लास के साथ पहले स्मृति में संयोजित किया जा सकता है, ताकि प्रत्येक बेस-क्लास सदस्य ऑब्जेक्ट के सापेक्ष एक ही स्थान पर हो पता करें कि ऑब्जेक्ट B या D है या नहीं। इससे पॉइंटर-टू-सदस्य-B को पॉइंटर-टू-सदस्य-D में कनवर्ट करना आसान हो जाता है; दोनों को वस्तु के पते से ऑफसेट के रूप में दर्शाया जा सकता है।

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

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

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