2009-11-05 13 views
9

अगर मैं सी ++ में है:सी ++ वर्चुअल फ़ंक्शन कार्यान्वयन?

class A { 
    private: virtual int myfunction(void) {return 1;} 
} 

class B: public A { 
    private: virtual int myfunction(void) {return 2;} 
} 

फिर अगर मैं class B में myfunction परिभाषा से virtual निकालने के लिए, इसका मतलब यह है कि अगर मैं एक class Cclass B पर आधारित है, के लिए किया था कि मैं इसे के बाद से myfunction ओवरराइड नहीं कर सका स्थिर रूप से संकलित किया जाएगा?

इसके अलावा, मैं उलझन में हूं कि जब आप सार्वजनिक रूप से स्विच करते हैं, और यहां निजी होते हैं तो क्या होता है। यदि मैं की परिभाषा class B में सार्वजनिक होने के लिए बदलता हूं (और class A में से एक निजी रहता है), क्या यह किसी प्रकार की गंभीर त्रुटि है जो मुझे नहीं करना चाहिए? मुझे लगता है कि वर्चुअल फ़ंक्शंस को एक ही प्रकार को रखने की आवश्यकता है ताकि यह अवैध हो, लेकिन कृपया यह बताएं कि क्या यह गलत है।

धन्यवाद!

+5

व्युत्पन्न क्लास विधियों के लिए स्पष्ट रूप से "वर्चुअल" कीवर्ड लिखने की आवश्यकता नहीं है। आप इसे छोड़ सकते हैं, लेकिन यह एक अच्छी शैली है। – varnie

उत्तर

15

'आभासी' के साथ पहली परिभाषा वह है जो मायने रखती है। बेस से वह फ़ंक्शन तब से वर्चुअल पर होता है जब से व्युत्पन्न होता है, जिसका अर्थ है कि आपको वर्चुअल फ़ंक्शन कॉल के लिए 'वर्चुअल' की आवश्यकता नहीं है। यदि बेस क्लास में फ़ंक्शन हस्ताक्षर वर्चुअल नहीं है, लेकिन व्युत्पन्न कक्षाओं में वर्चुअल है, तो बेस क्लास में पॉलीमोर्फिक व्यवहार नहीं है।

class Base 
{ 
    public: 
    void func(void){ printf("foo\n"); } 
}; 
class Derived1 : public Base 
{ 
    public: 
    virtual void func(){ printf("bar\n"); } 
}; 
class Derived2 : public Derived1 
{ 
    public: 
    /* reimplement func(), no need for 'virtual' keyword 
     because Derived1::func is already virtual */ 
    void func(){ printf("baz\n"); } 
}; 

int main() 
{ 
    Base* b = new Derived1; 
    Derived1* d = new Derived2; 

    b->func(); //prints foo - not polymorphic 
    d->func(); //prints baz - polymorphic 
} 
+0

धन्यवाद, यह बहुत उपयोगी था! – ash

+0

आपका स्वागत है। मुझे यह भी जोड़ना चाहिए कि "बेस * बी" वास्तव में एक व्युत्पन्न 1 है। आपको आवश्यक स्थितियों में सुरक्षित डाउनकास्टिंग करने के लिए dynamic_cast का उपयोग करें। –

+0

लेकिन लेखक उदाहरण निजी सदस्यों को शामिल करते हैं। – bua

1

यदि आप को दूर वर्ग बी में myfunction परिभाषा से virtual,

संकलक आप के लिए इस जोड़ देगा। पॉलिमॉर्फिक प्रकारों के लिए वी-टेबल भरने के लिए।

!! लेकिन !! (कक्षा बी: सार्वजनिक ए)

आप केवल वर्ग ए की जनता के सदस्यों के लिए उपयोग होगा

परिभाषा:

class B: private A 
{ 

} 

कारण होगा कि सभी (यहां तक ​​कि सार्वजनिक) वर्ग एक के सदस्यों, होगा कक्षा बी के लिए निजी बनें सरल बनाता है कि आपके पास सार्वजनिक सदस्यों तक पहुंच नहीं होगी।

वैकल्पिक हल के लिए आप कुछ दोस्त घोषणा कर सकते हैं:

class A 
{ 
    private: 
     friend class B; 
} 

अधिक महान जानकारी HERE

+0

त्वरित उत्तर के लिए धन्यवाद! – ash

+0

उत्तर मेरे लिए थोड़ा उलझन में है। उत्तर से मैंने पढ़ा है कि कक्षा बी उन कक्षा सदस्यों से नहीं पहुंच सकता है जिन्हें वह कक्षा ए से विरासत में मिला है, जिसे बाद में बी के मित्र घोषित करके हल किया जाता है। मुझे नहीं लगता कि यह सही होगा। बी ए से सार्वजनिक और संरक्षित सदस्यों तक पहुंच सकता है लेकिन बी के उपयोगकर्ता ए के सार्वजनिक सदस्यों तक नहीं पहुंच सकते हैं और यह मित्र घोषणा द्वारा हल नहीं किया जाएगा। क्या मैं कुछ गलत व्याख्या कर रहा हूँ? – stefaanv

+0

हां, आपने मेरे उदाहरण से निजी विरासत को याद किया है। – bua

7

एक बार फ़ंक्शन को बेस क्लास में वर्चुअल बना दिया जाता है, तो यह हर दूसरे उप-वर्ग के लिए वर्चुअल होगा।

सार्वजनिक, संरक्षित और निजी कार्यों की आभासी प्रकृति को प्रभावित नहीं करते हैं।

+0

धन्यवाद! दृश्यता जानकारी के लिए धन्यवाद। – ash

+0

अपने वर्चुअल फ़ंक्शंस को सुरक्षित या निजी बनाकर आप अपने वर्ग के उपयोगकर्ताओं को संकेत दे सकते हैं अगर उन्हें उप-वर्ग में कॉल करने की आवश्यकता हो या नहीं। http://www.gotw.ca/publications/mill18.htm –

0

virtual के व्यवहार है कि यह प्रभाव आप एक प्रकार है कि एक उप-प्रकार का एक उद्देश्य के लिए अंक की एक सूचक है जब कि कौन सी विधि कहा जाता है। उदाहरण के लिए:

B* obj = new B; 
A* base = obj; 

क्या होता है जब आप obj->myfunction() फोन A वाणी है कि क्या myfunction आभासी होने के लिए पर निर्भर करता है। यदि यह वर्चुअल नहीं है, तो तर्क यह है कि: हमारे पास A प्रकार का सूचक है, इसलिए हम A में परिभाषित फ़ंक्शन को कॉल करते हैं, और परिणाम 1 है।यदि A वर्चुअल होने के लिए myfunction को परिभाषित करता है, तो, पॉइंटर के प्रकार की बजाय वास्तविक ऑब्जेक्ट के प्रकार के आधार पर रन-टाइम पर एक लुक-अप किया जाता है; चूंकि ऑब्जेक्ट वास्तव में B है, B में परिभाषित कार्यान्वयन का उपयोग किया जाता है और परिणाम 2.

और जानकारी the C++ FAQ Lite section on virtual functions में मिल सकती है।

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