C++

2010-02-09 11 views
7

आपरेशन डालने के बाद बच्चे में आभासी समारोह का उपयोग करना मैं निम्नलिखित कोड है:C++

class A 
{ 
}; 

class B : public A 
{ 
    public: 
     virtual void f() {} 
}; 

int main() 
{ 
    A* a = new A(); 
    B* b = static_cast<B*>(a); 
    b->f(); 
} 

इस कार्यक्रम के एक विभाजन गलती के साथ विफल रहता है। इस कार्यक्रम काम करने के लिए दो समाधान हैं:

  1. घोषित च गैर आभासी
  2. कॉल नहीं करते बी> च() (यानी यह कलाकारों की वजह से नहीं विफल रहता है)

हालांकि , दोनों एक विकल्प नहीं हैं। मुझे लगता है कि यह vtable में एक लुकअप के कारण काम नहीं करता है।

(वास्तविक कार्यक्रम में, एक भी आभासी कार्यों है। इसके अलावा, आभासी समारोह निर्माता में नहीं बुलाया जाता है।)

वहाँ इस कार्यक्रम काम करने के लिए कोई तरीका है?

+1

+1 एक अच्छी तरह से स्वरूपित 1 प्रश्न के लिए। –

+0

इस मामले में, आप गतिशील_कास्ट पसंद कर सकते हैं, जो ए * ए = नया ए() के साथ "असफल" (वापसी शून्य) होगा, लेकिन ए * ए = नया बी() के साथ सफल होगा। आपको यह जांचना होगा कि बी बी कॉल करने से पहले शून्य नहीं है -> f()। – jmanning2k

उत्तर

12

आपको लगता है कि क्योंकि वस्तु आपके द्वारा बनाए गए एक, नहीं बी आपका डाली एक की एक वस्तु invalid-- है (नई के साथ बनाया) नहीं कर सकते जादुई बी

की

पात्र बन नहीं कर सकते हैं क्या मतलब ए * ए = नया ए() वास्तव में ए * ए = नया बी() होना चाहिए? उस स्थिति में, मैं इसे काम करने की उम्मीद करता हूं।

+0

आपके उत्तर के लिए धन्यवाद (सभी)। मैं इस बारे में सोच रहा हूं: यदि मैं वर्चुअल कीवर्ड को छोड़ देता हूं तो यह प्रोग्राम क्यों काम करता है? (शेष कोड अपरिवर्तित बनी हुई है।) मैंने f() (एक साधारण cout) में कुछ कार्यक्षमता डालने की कोशिश की और इसे निष्पादित किया गया। यदि यह बी प्रकार का ऑब्जेक्ट नहीं है, तो यह संभव नहीं होना चाहिए। सही? – Alexander

+2

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

+1

(जारी रखा गया, अंतरिक्ष की बाधाओं के कारण) इसलिए गैर-वर्चुअल फ़ंक्शन के साथ, 'बी-> एफ() '(उर्फ' बी :: एफ (बी) ') कॉल वास्तव में कभी भी * बी * का उपयोग नहीं करता है 'सूचक, जब तक 'बी :: एफ' कार्यक्षमता 'बी' ऑब्जेक्ट में निहित डेटा तक पहुंचने का प्रयास नहीं करती है। यदि 'बी :: एफ' बॉडी बस 'cout' कथन है, तो कोई स्पष्ट समस्या नहीं होगी। यदि आप उदाहरण के लिए 'बी' कक्षा के अंदर एक पूर्णांक सदस्य को परिभाषित करते हैं और इसे 'बी :: एफ' में प्रिंट करने का प्रयास करते हैं, तो आपको उस पूर्णांक के लिए एक segfault, या एक विचित्र अप्रत्याशित मान प्राप्त होगा। –

2

आदेश में एक static_cast करने के लिए, आप यह सुनिश्चित करें कि वस्तु casted जा कर सकते हैं होना चाहिए, जैसे वर्ग B का एक उद्देश्य है।

इस मामले में, मुझे यकीन है कि यह नहीं है।

3

आप ऐसा नहीं कर सकते हैं।

अपने उदाहरण में, एक वर्ग ए नहीं बी बी के लिए यह कास्टिंग आप बहुरूपी वस्तु व्यवहार उपयोग करना चाहते हैं यह एक बी

नहीं है की एक वस्तु है, तो आप आभासी समारोह च दे सकते हैं वर्ग एक के लिए, और आप जैसे A* a = new B(); तो फिर तुम आभासी कार्यों एक सूचक के माध्यम से वर्ग बी

3

से व्यवहार प्राप्त करने के लिए अपने कोड में उपयोग कर सकते हैं कोड का उपयोग कर सकते हैं:

A* a = new A(); 

आप एक A वस्तु का दृष्टांत। तो फिर तुम static_cast उपयोग करने के लिए एक आधार के प्रकार से एक व्युत्पन्न प्रकार के लिए जाने की कोशिश: अगर a में मूल्य एक वस्तु है कि वास्तव में प्रकार B की ओर इशारा किया था

B* b = static_cast<B*>(a); 

, यह कानूनी और अच्छी तरह से गठित किया जाएगा। लेकिन aB के किसी ऑब्जेक्ट को इंगित नहीं करता है, यह A पर इंगित करता है, इसलिए कलाकार अपरिभाषित व्यवहार को प्रेरित करता है।

यह तय करना है कि आप ऑब्जेक्ट को तुरंत कैसे चालू करते हैं। परिवर्तित करें:

A* a = new A(); 

... करने के लिए:

A* a = new B();