2010-08-22 15 views
11

साथ एकाधिक वंशानुक्रमसी ++: बहुरूपता

(अग्रिम में noob सवाल क्षमा) मैं 4 वर्गों है:

class Person {}; 
class Student : public Person {}; 
class Employee : public Person {}; 
class StudentEmployee : public Student, public Employee {}; 

मूलतः Person आधार वर्ग, जो सीधे Student और Employee दोनों द्वारा subclassed कर रहे हैं। StudentEmployeeStudent और Employee दोनों को उपclass करने के लिए एकाधिक विरासत कार्यरत है।

Person pat = Person("Pat"); 
Student sam = Student("Sam"); 
Employee em = Employee("Emily"); 
StudentEmployee sen = StudentEmployee("Sienna"); 


Person ppl[3] = {pat, sam, em}; 
//compile time error: ambiguous base class 
//Person ppl[4] = {pat, sam, em, sen}; 

जब मैं Person की एक सरणी का उपयोग करें, आधार वर्ग, मैं Person और उसके उपवर्गों के सभी इस सरणी के अंदर डाल सकते हैं। संदिग्ध आधार वर्ग के कारण दिए गए StudentEmployee के अलावा।

यह देखते हुए कि StudentEmployeePerson के सभी तरीकों और विशेषताओं की गारंटी है, StudentEmployee व्यक्ति का उप-वर्ग माना जाता है?

  • यदि ऐसा है, तो संकलक मुझे ऑब्जेक्ट को अपने सुपरक्लास के प्रकार के चर के लिए असाइन करने की अनुमति क्यों नहीं देता है?
  • यदि नहीं, तो क्यों नहीं; और इसे पूरा करने का सही तरीका क्या होगा?

चीयर्स


संपादित करें: preemptively, इस प्रश्न का अनुसरण में से किसी एक नहीं है:
polymorphism relates inheritance
Inheritance mucking up polymorphism in C++?

उत्तर

13

StudentEmployee निश्चित रूप से Person का उप-वर्ग है। समस्या यह है कि दो बार: यह अप्रत्यक्ष रूप से Person दो बार (Student और एक बार Employee के माध्यम से) प्राप्त करता है और यही कारण है कि आपको "संदिग्ध आधार वर्ग" त्रुटि मिलती है। सुनिश्चित करें कि StudentEmployee केवल विरासत Person एक बार, तो आप ऐसा तरह, आभासी विरासत उपयोग करने के लिए:

class Person {}; 
class Student : public virtual Person {}; 
class Employee : public virtual Person {}; 
class StudentEmployee : public Student, public Employee {}; 

यह आपके त्रुटि को ठीक होगा।

आपके कोड के साथ एक और बड़ी समस्या है, और इसे slicing कहा जाता है।

जब आप ऐसा करते:

Person ppl[3] = {pat, sam, em}; 

तीन Person वस्तुओं की एक सरणी बनाया जाएगा लेकिन उन वस्तुओं कॉपी Person वर्ग की परोक्ष परिभाषित प्रतिलिपि निर्माता का उपयोग कर निर्माण किया जाएगा। अब, इसके साथ समस्या यह है कि आपकी सरणी में ऑब्जेक्ट्स केवल Person ऑब्जेक्ट्स होंगे और उप-वर्गों की ऑब्जेक्ट्स नहीं जिन्हें आप चाहते हैं।

इसे ठीक करने के लिए आप इस तरह Person वस्तुओं की ओर इशारा की एक सरणी बनाने के लिए, होगा:

Person* ppl[] = {new Person("Pat"), new Student("Sam"), 
       new Employee("Emily"), new StudentEmployee("Sienna")}; 

या

Person* ppl[] = {&pat, &sam, &em, &sen}; 
+0

लेकिन जाहिर है, इस तरह की नई कॉलिंग निश्चित रूप से स्लाइसिंग के लिए मेमोरी लीक – Falmarri

+1

+1 की ओर ले जाएगी। और अगर बगुइज़ पहले से ही नहीं जानता था, तो यह व्यक्ति * पीपीएल [] = {और पेट, और सैम, और एम, &sen }; भी हो सकता है - इन दो विकल्पों के मेमोरी प्रबंधन में थोड़ा अंतर है। – Michael

+0

@ फाल्मररी: क्यों? आपके पास अभी भी पॉइंटर्स की सरणी है। – Job

3

वहाँ का एक उद्देश्य से दो समान रूप से संभव रास्ते हैं टाइप करें Person

आपको virtual दोनों Student और Employee कक्षाओं के लिए कीवर्ड का उपयोग करने की आवश्यकता है। FAQ 25.8 देखें वास्तव में उस पूरे खंड से गुज़रें।

+0

धन्यवाद, उस लेख सिर पर कील मारा ! – bguiz

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

  • कोई संबंधित समस्या नहीं^_^