दिलचस्प पोस्ट
$ .jax की सफलता और .done () विधि के बीच अंतर क्या है मैं MySQL में एक अनुक्रम कैसे बनाऊं? जावा में फ़्लोट्स के साथ प्रेसिजन त्रुटि अजगर का क्या अर्थ है पायथन में? पायथन के साथ पायथन उपप्रोसेस कमांड क्या सक्रिय विंडो पर विंडोज सिस्टम ईवेंट बदल गया है? स्थानांतरित वस्तु से मैं क्या कर सकता हूं? एसक्यूएल में शामिल होने के मामले क्या है? रेडयुक्स ऐप में स्थानीय स्टॉरेज को कहाँ लिखना है? 'ज़ोरदार' जावास्क्रिप्ट चर एम्परसेंड के साथ PHP फ़ंक्शन शुरू करने का क्या अर्थ है? जावा से चलने वाली MATLAB फ़ंक्शन नेंट या एमएसबीइल्ड, जो एक को चुनने के लिए और कब? मैं एएसपी.नेट एमवीसी में एसिंक कंट्रोलर्स का उपयोग कब करना चाहिए? एक UITableView की "उछाल क्षेत्र" में हल्की भूरे रंग की पृष्ठभूमि

आभासी विरासत "हीरा" (एकाधिक वंशानुक्रम) अस्पष्टता कैसे हल करती है?

class A { public: void eat(){ cout<<"A";} }; class B: virtual public A { public: void eat(){ cout<<"B";} }; class C: virtual public A { public: void eat(){ cout<<"C";} }; class D: public B,C { public: void eat(){ cout<<"D";} }; int main(){ A *a = new D(); a->eat(); } 

मैं हीरा की समस्या को समझता हूं, और कोड के ऊपर उस समस्या की समस्या नहीं है।

आभासी विरासत समस्या को हल कैसे करता है?

मैं क्या समझता हूँ: जब मैं कहता हूँ A *a = new D(); , कंपाइलर जानना चाहता है कि टाइप D का एक ऑब्जेक्ट टाइप A एक सूचक को सौंपा जा सकता है, लेकिन इसमें दो मार्ग हैं जिनका वह पालन कर सकता है, लेकिन खुद तय नहीं कर सकता है।

तो, आभासी विरासत को कैसे हल करता है (मदद संकलक निर्णय लेता है)?

वेब के समाधान से एकत्रित समाधान "आभासी विरासत "हीरा" (एकाधिक वंशानुक्रम) अस्पष्टता कैसे हल करती है?"

आप चाहते हैं: (आभासी विरासत के साथ प्राप्त)

  D / \ BC \ / A 

और नहीं: (वर्चुअल विरासत के बिना क्या होता है)

  D / \ BC | | AA 

आभासी वंशानुक्रम का मतलब है कि आधार A कक्षा 2 का केवल 1 उदाहरण होगा

आपके टाइप D में 2 वीटेबल पॉइंटर्स होंगे (आप उन्हें पहली आरेख में देख सकते हैं), एक B और एक C जो कि वस्तुतः A उत्तराधिकारी है। D का ऑब्जेक्ट आकार बढ़ गया है क्योंकि यह अब 2 पॉइंटर्स स्टोर करता है; हालांकि अब केवल एक A

तो B::A और C::A समान हैं और इसलिए D से कोई अस्पष्ट कॉल नहीं हो सकता। यदि आप आभासी विरासत का उपयोग नहीं करते हैं तो आपके पास दूसरा चित्र ऊपर है। और ए के किसी सदस्य को कोई कॉल अस्पष्ट हो जाती है और आपको निर्दिष्ट करना है कि आप किस मार्ग को लेना चाहते हैं।

विकिपीडिया के पास एक अच्छा ठहरनेवाला और उदाहरण है

व्युत्पन्न कक्षाओं के उदाहरणों में "आधार वर्गों" के उदाहरण होते हैं, इसलिए वे इस तरह की स्मृति में दिखते हैं:

 class A: [A fields] class B: [A fields | B fields] class C: [A fields | C fields] 

इस प्रकार, आभासी विरासत के बिना, कक्षा डी का उदाहरण दिखता है:

 class D: [A fields | B fields | A fields | C fields | D fields] '- derived from B -' '- derived from C -' 

इसलिए, ए डेटा के दो "कॉपी" नोट करें आभासी विरासत का मतलब है कि अंदर के व्युत्पन्न वर्ग में रनटाइम पर एक vtable सूचक सेट होता है जो आधार वर्ग के डेटा को इंगित करता है, ताकि बी, सी और डी कक्षाओं के उदाहरण दिखते हैं:

 class B: [A fields | B fields] ^---------- pointer to A class C: [A fields | C fields] ^---------- pointer to A class D: [A fields | B fields | C fields | D fields] ^---------- pointer to B::A ^--------------------- pointer to C::A 

समस्या संकलक को जिस पथ का पालन करना चाहिए वह नहीं है। समस्या उस पथ का समापन बिंदु है: कास्ट का नतीजा। जब यह रूपांतरणों को लिखने के लिए आता है, तो पथ कोई फर्क नहीं पड़ता, केवल अंतिम परिणाम होता है

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

यदि आप आभासी विरासत का उपयोग करते हैं, तो आपको एक हीरा के आकार का पदानुक्रम मिलता है: दोनों रास्ते उसी समापन बिंदु पर ले जाते हैं। इस मामले में पथ चुनने की समस्या अब मौजूद नहीं है (या, अधिक सटीक, अब कोई मायने नहीं), क्योंकि दोनों रास्ते एक ही परिणाम के लिए आगे बढ़ते हैं। नतीजा अब अस्पष्ट नहीं है – यह क्या मायने रखता है सटीक पथ नहीं है

दरअसल, उदाहरण निम्न होना चाहिए:

 #include <iostream> //THE DIAMOND PROBLEM SOLVED!!! class A { public: virtual ~A(){ } virtual void eat(){ std::cout<<"EAT=>A";} }; class B: virtual public A { public: virtual ~B(){ } virtual void eat(){ std::cout<<"EAT=>B";} }; class C: virtual public A { public: virtual ~C(){ } virtual void eat(){ std::cout<<"EAT=>C";} }; class D: public B,C { public: virtual ~D(){ } virtual void eat(){ std::cout<<"EAT=>D";} }; int main(int argc, char ** argv){ A *a = new D(); a->eat(); delete a; } 

… इस तरह से आउटपुट सही होने वाला है: "EAT => D"

आभासी विरासत केवल दादा के दोहराव को हल करती है! लेकिन तरीकों को सही तरीके से ओवरराइड करने के लिए आपको आभासी होने के तरीकों को अभी भी निर्दिष्ट करना होगा …

यह समस्या आभासी कीवर्ड का उपयोग करके हल कर सकती है।

  A / \ BC \ / D 

डायमंड समस्या का उदाहरण

 #include<stdio.h> using namespace std; class AA { public: int a; AA() { a=10; } }; class BB: virtual public AA { public: int b; BB() { b=20; } }; class CC:virtual public AA { public: int c; CC() { c=30; } }; class DD:public BB,CC { public: int d; DD() { d=40; printf("Value of A=%d\n",a); } }; int main() { DD dobj; return 0; } 
 #include <iostream> class A { public: virtual ~A(){ } virtual void eat(){ std::cout<<"EAT=>A";} }; class B: virtual public A { public: virtual ~B(){ } virtual void eat(){ std::cout<<"EAT=>B";} }; class C: virtual public A { public: virtual ~C(){ } virtual void eat(){ std::cout<<"EAT=>C";} }; class D: public B,C { public: virtual ~D(){ } }; int main(int argc, char ** argv){ A *a = new D(); a->eat(); delete a; }