2012-11-19 15 views
13

मान लीजिए मैं निम्नलिखित कोड है:मुझे C++ में व्युत्पन्न कक्षाओं में ओवरराइड फ़ंक्शंस को फिर से घोषित क्यों करना है?

class Iinterface 
{ 
    virtual void abstractFunction()=0; 
}; 

class Derived : public Iinterface 
{ 
    void abstractFunction(); // Do I need this line? 
}; 

Derived::abstractFunction() 
{ 
    // implementation here 
} 

मैं प्रश्न में लाइन जोड़ने नहीं है, तो मैं त्रुटि जो कहते हैं abstractFunctionDerived में घोषित नहीं किया गया है संकलन मिलता है। मैं वीएस 2008 का उपयोग कर रहा हूं।
मुझे यकीन नहीं है कि मुझे इस विशेष लाइन की आवश्यकता क्यों है (कक्षा की घोषणा के बाहर प्रदान की गई फ़ंक्शन परिभाषा के साथ इसे भ्रमित न करें), जब तक मैं Iinterface से विरासत में हूं, स्पष्ट हो मेरे पास abstractFunction घोषित किया गया है। क्या यह दृश्य स्टूडियो के साथ एक समस्या है या इसे सी ++ मानकों द्वारा लागू किया गया है?

उत्तर

8

यदि शुद्ध व्युत्पन्न आधार कार्यों की घोषणा सभी व्युत्पन्न कक्षाओं में निहित की गई थी, तो आपके पास कभी व्युत्पन्न कक्षा नहीं हो सकती जो शुद्ध-वर्चुअल बेस फ़ंक्शन के संबंध में सार बना रहता है। इसके बजाए, सभी व्युत्पन्न वर्ग लिंकर त्रुटियों का उत्पादन करेंगे। यह बेहद उलझन में और भ्रमित होगा, और यह भाषा को कम अभिव्यक्ति देगा।

इसके अलावा, यह भी समझ में नहीं आता है: सवाल यह है कि व्युत्पन्न वर्ग सार है या संकलित समय पर हर जगह ज्ञात नहीं होना चाहिए। ओवरराइडर का कार्यान्वयन आम तौर पर केवल एक एकल अनुवाद इकाई में प्रदान किया जाता है, इसलिए इस तथ्य को संवाद करना असंभव होगा कि वास्तव में कार्य के बाकी कार्यक्रम में ओवरराइड होने के लिए आपका मतलब है।

+0

आपने इसे बहुत बेहतर समझा है :) –

+0

मैं मानता हूं, यह शायद मेरे रैंपिंग उत्तर, +1 से अधिक समझ में आता है। – OmnipotentEntity

+0

क्या व्युत्पन्न वर्ग सार है या नहीं, एक स्पष्ट "अमूर्त" कीवर्ड के साथ जाना जा सकता है जिसे सी ++ की कमी है। –

0

हां, शुद्ध वर्चुअल फ़ंक्शन का पूरा बिंदु यह लागू करना है कि आप इसे व्युत्पन्न कक्षा में ओवरराइड करें; इस घोषणा C++

+0

मुझे इसके बारे में पता है, और मैं ** ** इसे ओवरराइड कर रहा हूं, मुझे समझ में नहीं आता कि मुझे वर्ग घोषणा के भीतर फ़ंक्शन के प्रोटोटाइप को फिर से लिखने की आवश्यकता क्यों है। वीएस खुद का अनुमान क्यों नहीं लगाएगा? – atoMerz

+0

वीएस सोचता है कि आप उस मेटोड के बारे में भूल गए हैं :) – whd

+0

क्योंकि क्लास परिभाषा ऑब्जेक्ट पदानुक्रम डिज़ाइन को चलाती है, यदि आप करेंगे; जैसा कि उपरोक्त समझाया गया है, ओवरराइड घोषणा को शामिल करना है या नहीं, आपकी पसंद है कि संकलक बताता है कि संबंधित विधि कोड होना चाहिए या नहीं। –

2
  1. हाँ में स्पष्ट हो गया है: आप class Derived
  2. नहीं की एक वस्तु बनाने के लिए करना चाहते हैं: आप class Derived भी सार
  3. रखना चाहते हैं नहीं: यदि कोई इंटरमीडिएट क्लास है जो पहले से ही
    फ़ंक्शन को ओवरराइड कर चुका है Iinterface और Derived के बीच class Intermediate है जो abstractFunction() ओवरराइड किया गया है; मैं क्यों C++ में व्युत्पन्न वर्ग में ओवरराइड कार्यों को फिर से घोषित करने के लिए गए हैं बदल सवाल शीर्षक के साथ,

    : तो अब यह class Derived ही

संपादित ओवरराइड करने के लिए के लिए वैकल्पिक है?

ऐसा इसलिए है क्योंकि सी ++ संकलक व्याकरण की मांग है कि class (या namespace या फ़ाइल) के हर सदस्य समारोह class (या namespace या फ़ाइल) शरीर के अंदर घोषित किया जाना चाहिए है। यह virtual या सामान्य कार्य हो।
कोईvirtual फ़ंक्शंस के लिए उस स्थिरता को तोड़ने का अच्छा कारण है।

+1

मुझे लगता है कि ओपी एक शुद्ध वर्चुअल बेस फ़ंक्शन को ओवरराइड करने के यांत्रिकी के बारे में जानता है। वह जानना चाहती है कि व्युत्पन्न कक्षा में * घोषणा * क्यों आवश्यक है। –

+0

@KerrekSB धन्यवाद, यही मेरा मतलब है। – atoMerz

+0

@KerrekSB, ऐसा लगता है कि प्रश्न का शीर्षक अभी संपादित किया गया है। मैं जवाब संशोधित करूंगा। – iammilind

1

एक समारोह है कि एक =0 में समाप्त होता है एक deleted function कहा जाता है, यह उपयोगी होता है जब आप वस्तुओं है कि कुछ निर्माताओं (जैसे unique_ptr जो एक नष्ट कर दिया प्रतिलिपि ctor है के रूप में) का उपयोग नहीं करना चाहती।

यदि virtual फ़ंक्शन हटा दिया जाता है तो मानक मानक वर्ग बन जाता है। चूंकि ज्यादातर मामलों में कक्षा और वर्ग के फ़ंक्शन निकायों का प्रोटोटाइप अलग-अलग फ़ाइलों में होता है, इसका अर्थ यह है कि जब तक आप स्पष्ट रूप से प्रोटोटाइप में रूपरेखा नहीं देते हैं कि आप हटाए गए वर्चुअल फ़ंक्शन को ओवरराइड कर रहे हैं तो आप हटाए गए वर्चुअल फ़ंक्शन को ओवरराइड नहीं कर रहे हैं। कंपाइलर को केवल यह अनुमान लगाने की आवश्यकता नहीं है कि एक बार पूरी तरह से अलग फ़ाइल में कार्यान्वयन को देखने के बाद आप उस समारोह को वहां रखना चाहते थे।

याद रखें कि प्रोटोटाइप/कार्यान्वयन विचार कोड लिखने का एकमात्र तरीका नहीं है, आप कक्षा में कार्यान्वयन को सही भी डाल सकते हैं (यदि कोड पर्याप्त छोटा हो और आप फ़ंक्शन को इनलाइन करना चाहते हैं तो किया जा सकता है।) और ऐसा करने के लिए आपको फिर से हटाने की आवश्यकता है, हटाए गए वर्चुअल फ़ंक्शन को स्पष्ट रूप से ओवरराइड करें। इसलिए क्योंकि आपको इसे किसी भी तरह से ओवरराइड करने की आवश्यकता है, यह सही समझ में आता है कि आपको इसे प्रोटोटाइप में स्पष्ट रूप से ओवरराइड करने की आवश्यकता है। फ़ंक्शन अभी भी हटा दिया गया है अन्यथा।

एक ठोस उदाहरण के लिए: मान लीजिए कि आप एक List.hpp, List.cpp और main.cpp

List.hpp में आप एक अमूर्त वर्ग और एक नियमित रूप से वर्ग कि अमूर्त वर्ग से विरासत कर सकते है। मुख्य में आप #include "List.hpp" और List.cpp नहीं, है ना? इसलिए कंपाइलर में कोई आईडीईए नहीं है जो उस फ़ाइल में है (जब तक कि इसे संकलित करने का प्रयास न हो।) यदि आपके पास हटाए गए वर्चुअल फ़ंक्शन को ओवरराइड नहीं किया गया है तो संकलक सोचता है कि आप बस एक सार वर्ग को तुरंत चालू करने और त्रुटि को फेंकने की कोशिश कर रहे हैं।

दूसरी ओर, यदि आप List.cpp संकलित कर रहे हैं, तो संकलक भी एक त्रुटि फेंक देगा, इस बार शिकायत करेगा कि जिस फ़ंक्शन को आप लिखने का प्रयास कर रहे हैं उसे वास्तव में परिभाषित नहीं किया गया है। क्योंकि Base::deletedFunction()Derived::deletedFunction() से अलग है।

+0

धन्यवाद। क्या यह एक कंपाइलर सीमा या सी ++ सीमा है? – atoMerz

+1

सी ++ सीमा। हालांकि मैं इसे एक सीमा कहने में संकोच करूंगा। यह बस इतना है कि आपको इसके बारे में स्पष्ट होना है। जो आपको लंबे समय तक मदद करता है, इमो। – OmnipotentEntity

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