2015-06-11 18 views
10

मैं के रूप में प्रदर्शित करने के लिए कैसे एक शुद्ध आभासी समारोह कहा जा सकता है this answer में उदाहरण के लिए "मरम्मत" की कोशिश की।यह शुद्ध वर्चुअल फ़ंक्शन का कॉल क्यों नहीं है?

#include <iostream> 
using namespace std; 

class A 
{ 
    int id; 
public: 
    A(int i): id(i) {} 
    int callFoo() { return foo(); } 
    virtual int foo() = 0; 
}; 

class B: public A 
{ 
public: 
    B(): A(callFoo()) {} 
    int foo() { return 3; } 
}; 

int main() { 
    B b; // <-- this should call a pure virtual function 
    cout << b.callFoo() << endl; 
    return 0; 
} 

लेकिन मुझे कोई रनटाइम त्रुटि here (with C++ 4.9.2) मिलता है, लेकिन उत्पादन 3. मैं बोर्लेन्ड सी ++ 5.6.4 के साथ एक ही करने की कोशिश की है, लेकिन वहाँ मैं एक पहुँच उल्लंघन हो रही है। मुझे लगता है कि foo() बेस क्लास के निर्माता के कॉल में शुद्ध वर्चुअल होना चाहिए।

कौन गलत है? क्या मुझे और कंपाइलर्स आज़माएं? क्या मैं आभासी कार्यों की मेरी समझ में सही हूं?

+4

मैं बोर्लेन्ड सी ++ के साथ एक परीक्षण के परिणामों का प्रयोग नहीं होता है, तो कोड का एक टुकड़ा वैध और/या मानक के अनुरूप है देखने के लिए;) – CoryKramer

+0

@CoryKramer आभासी कार्यों अब दशकों के लिए उपयोग में हैं। – Wolf

+1

मुझे इसके बारे में पता है, मैं अभी भी बोर्लैंड आईडीई – CoryKramer

उत्तर

14

आपके कोड में अनिर्धारित व्यवहार है: यह किसी भी ऑब्जेक्ट (यहां तक ​​कि एक गैर-आभासी एक) पर सदस्य फ़ंक्शन को कॉल करने के लिए यूबी है, इसके सभी मूल वर्ग प्रारंभ किए जाने से पहले। सी ++ 14 (एन 4140) 12.6.2/14, जोर मेरा:

सदस्य कार्य (आभासी सदस्य कार्यों सहित, 10.3) निर्माण के तहत किसी वस्तु के लिए बुलाया जा सकता है। इसी तरह, निर्माण के तहत एक वस्तु typeid ऑपरेटर (5.2.8) या dynamic_cast (5.2.7) का संचालन हो सकती है। हालांकि, (या एक समारोह में कहा जाता है सीधे या परोक्ष रूप से एक ctor-प्रारंभकर्ता से) इन आपरेशनों एक ctor-प्रारंभकर्ता में प्रदर्शन कर रहे हैं अगर सब मेम-initializers आधार वर्ग के लिए पूरा कर लिया है, परिणाम से पहले ऑपरेशन अपरिभाषित है। ...

ctor-प्रारंभकर्ता निम्नलिखित : पूरी सूची है। मेम-प्रारंभकर्ता इस सूची का एक तत्व है।

+0

सच है और यह यूबी नियम अच्छी तरह से स्थापित है। लेकिन यह केवल सिरदर्द को चलाता है - कोई संकलक नहीं और न ही स्थैतिक कोड चेकर सभी त्रुटियों को पायेगा। मुझे आश्चर्य हुआ कि इस तरह के सरल इनलाइन मामलों को तत्काल खारिज नहीं किया गया था। – Wolf

+0

@ वुल्फ: कंपाइलर [पूर्ण नियंत्रण-प्रवाह विश्लेषण करने की आवश्यकता नहीं है] (http://blogs.msdn.com/b/oldnewthing/archive/2013/10/11/10455907.aspx), क्योंकि यह हो सकता है संकलन समय पर स्थिर रूप से करना संभव नहीं है। – Kevin

+0

@ केविन * शुद्ध वर्चुअल फ़ंक्शन से छुटकारा पाने के लिए शुद्ध वर्चुअल फ़ंक्शंस को कार्यान्वित करना * संदेश मुझे दुरुपयोग की तरह लगता है, या यह वास्तव में इस उद्देश्य के लिए डिज़ाइन किया गया था? – Wolf

5

कथन B b; डिफ़ॉल्ट कन्स्ट्रक्टर को B पर कॉल करता है।

B का निर्माण करते समय, B से संबंधित कुछ भी A पूरी तरह से निर्मित होने तक निर्मित नहीं है।

तो callFoo() पर कॉल करने का प्रयास करने में, व्यवहार अपरिभाषित है क्योंकि आप कक्षा B सेट अप के लिए v-table पर भरोसा नहीं कर सकते हैं।

सारांश में: एक अमूर्त वर्ग के निर्माण के दौरान शुद्ध वर्चुअल फ़ंक्शन को कॉल करने का व्यवहार अपरिभाषित है।

+0

देता है मैं अनुमान लगाया इस वजह मामला होगा। तो, ऐसा लगता है कि मैं अपने "मरम्मत" सुझाव के साथ आलसी था। – Wolf

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