2010-12-09 11 views
48

निम्न उदाहरण पर विचार करें:लर्निंग सी ++: बहुरूपता और टुकड़ा करने की क्रिया

#include <iostream> 
using namespace std; 

class Animal 
{ 
public: 
    virtual void makeSound() {cout << "rawr" << endl;} 
}; 

class Dog : public Animal 
{ 
public: 
    virtual void makeSound() {cout << "bark" << endl;} 
}; 

int main() 
{ 
    Animal animal; 
    animal.makeSound(); 

    Dog dog; 
    dog.makeSound(); 

    Animal badDog = Dog(); 
    badDog.makeSound(); 

    Animal* goodDog = new Dog(); 
    goodDog->makeSound(); 
} 

उत्पादन होता है:

rawr 
bark 
rawr 
bark 

लेकिन मैंने सोचा था कि निश्चित रूप से उत्पादन किया जाना चाहिए "rawr छाल छाल छाल"। BadDog के साथ क्या है?


अद्यतन: आपको another question of mine में रुचि हो सकती है।

+1

मुझे लगता है कि आपके चर के लिए कुछ नामकरण त्रुटियां हैं। – aioobe

+2

कोड भी संकलित नहीं है। और 'शून्य शून्य()' ??? ईडब्ल्यू ... –

+2

मुझे समझ में नहीं आ रहा है कि कोई इस सवाल को क्यों कम करेगा - यह न तो "अस्पष्ट" है और न ही "उपयोगी नहीं है"। डाउनवोट को अस्वीकार करने के लिए +1। सुंदर कुत्ते मेटाफोर के लिए – casablanca

उत्तर

64

यह "स्लाइसिंग" नामक एक समस्या है।

Dog()Dog ऑब्जेक्ट बनाता है। यदि आप Dog().makeSound() पर कॉल करना चाहते थे, तो यह "छाल" प्रिंट करेगा जैसा कि आप उम्मीद करते हैं।

समस्या यह है कि आप badDog प्रारंभ कर रहे हैं, जो इस Dog के साथ Animal प्रकार का एक ऑब्जेक्ट है। चूंकि Animal में केवल Animal हो सकता है और Animal से प्राप्त कुछ भी नहीं, Dog का हिस्सा लेता है और इसके साथ स्वयं को प्रारंभ करता है।

badDog का प्रकार हमेशा Animal है; यह कभी और कुछ नहीं हो सकता है।

सी ++ में पॉलिमॉर्फिक व्यवहार प्राप्त करने का एकमात्र तरीका पॉइंटर्स का उपयोग कर रहा है (जैसा कि आपने अपने goodDog उदाहरण के साथ प्रदर्शित किया है) या संदर्भों का उपयोग कर रहा है।

एक संदर्भ (जैसे, Animal&) किसी भी प्रकार Animal से ली गई और एक सूचक की एक वस्तु का उल्लेख कर सकते हैं (जैसे, Animal*) किसी भी प्रकार Animal से प्राप्त की एक वस्तु को इंगित कर सकते हैं। एक सादा Animal, हालांकि, हमेशा Animal है, और कुछ नहीं।

तरह जावा और सी # कुछ भाषाओं संदर्भ अर्थ विज्ञान, जहां चर (ज्यादातर मामलों में) कर रहे हैं सिर्फ वस्तुओं के लिए संदर्भ है, इसलिए दिए गए एक Animal rex;, rex वास्तव में कुछ Animal करने के लिए सिर्फ एक संदर्भ है, और rex = new Dog()rex एक नया करने का उल्लेख करता है Dog ऑब्जेक्ट।

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

+0

उत्कृष्ट स्पष्टीकरण। धन्यवाद! – JnBrymn

+4

मैं जोड़ूंगा कि मैंने जावा और सी # और सी ++ के प्रकार सिस्टम के बीच तुलना को व्यापक रूप से बढ़ाया है। –

+0

उत्तर और टिप्पणी के लिए +1 :) – suszterpatt

7
Animal badDog = Dog(); 
    ad.makeSound(); 

जब आप एक Dog का दृष्टांत और एक Animal चर करने के लिए दर-मूल्य में निर्दिष्ट करें, तो आप वस्तु slice। जिसका मूल रूप से मतलब है कि आप सभी Dog-badDog से परेशान करें और इसे बेस क्लास में बनाएं।

बेस कक्षाओं के साथ बहुरूपता का उपयोग करने के लिए, या तो पॉइंटर्स या संदर्भों का उपयोग करना चाहिए।

+0

+1 इसे छोटा और समेकित करने के लिए – starcorn

-1

आपने असाइनमेंट ऑपरेटर का उपयोग करके BadDog प्रारंभ किया। इस प्रकार कुत्ते() को पशु के रूप में कॉपी किया गया था। आपके कार्यक्रम का आउटपुट सही है। :)

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