2015-07-22 6 views
6

व्युत्पन्न कक्षा में विधि fun() निजी है। जब हम रन टाइम पॉलीमोर्फिज्म के माध्यम से ptr->fun() फ़ंक्शन को कॉल करते हैं, तो यह निष्पादित होता है। लेकिन यह व्युत्पन्न वर्ग की encapsulation संपत्ति का उल्लंघन करता है।क्या दोस्त का काम यहां विरासत में मिला है?

#include<iostream> 
using namespace std; 

class Derived; 

class Base { 
private: 
    virtual void fun() { cout << "Base Fun"; } 
friend int main(); 
}; 

class Derived: public Base { 
private: 
    void fun() { cout << "Derived Fun"; } 
}; 

int main() 
{ 
Base *ptr = new Derived; 
ptr->fun(); 
return 0; 
} 

क्या कोई यह बता सकता है कि क्या हो रहा है?

+0

दोस्तों के पास निजी सदस्यों के पास acces है। आप मुख्य को दोस्त के रूप में घोषित करते हैं, इसलिए निजी सदस्यों तक पहुंच है। (आपने यह क्यों किया है यह मेरे लिए एक चमत्कार है) – user463035818

+0

@ tobi303, मित्र के पास 'बेस' के निजी 'तक पहुंच' नहीं है और 'मजेदार()' प्रोग्राम चलाया जाने पर कॉल किया जा रहा है 'मजेदार() ' 'व्युत्पन्न 'वर्ग .. बीटीडब्ल्यू मैं सी ++ अवधारणाओं के साथ खेल रहा था, इसलिए इस पर आया .. व्यावहारिक कुछ भी नहीं .. – Haris

उत्तर

2

सबसे पहले, अपने Derived::fun() भी virtual, एक व्युत्पन्न वर्ग में एक समारोह आधार वर्ग में एक आभासी समारोह के रूप में एक ही घोषणा है तो व्युत्पन्न वर्ग में समारोह स्वचालित रूप से virtual हो जाता है क्योंकि है, भले ही कि स्पष्ट रूप से नहीं था निर्दिष्ट।

दूसरा, बेस क्लास से सार्वजनिक मध्यवर्ती कार्यों के माध्यम से निजी वर्चुअल फ़ंक्शंस तक पहुंचने के लिए पूरी तरह से ठीक है, उदाहरण के लिए, this answer और इसके लिंक, विशेष रूप से Virtuality by Herb Sutter। एक नमूना कोड हो सकता है की तरह

#include<iostream> 
using namespace std; 

class Derived; 

class Base { 
private: 
    virtual void fun() { cout << "Base Fun"; } 
public: 
    void funInt() { fun(); } 
}; 

class Derived: public Base { 
private: 
    virtual void fun() { cout << "Derived Fun"; } 
}; 

int main() 
{ 
Base *ptr = new Derived; 
ptr->funInt(); 
return 0; 
} 

तो, क्या अपने मामले में होता है, मुझे लगता है, एक ऐसी ही स्थिति है: mainptr->fun() का उपयोग करने की अनुमति दी है, लेकिन वास्तविकता के कारण इस fun()Derived::fun() होता है।

युपीडी: एक टिप्पणी

लेकिन करता है इस ध्वनि एक छोटे से खतरनाक नहीं पर विस्तार ..मेरा मतलब है, सभी कार्यों कि आधार वर्ग से निकाले जाते हैं, उनके निजी सदस्यों के लिए सुलभ बेस वर्ग के दोस्त कार्यों

नहीं, Derived के सभी कार्यों के दोस्तों के लिए सुलभ हो जाएगा Base, लेकिन केवल वे लोग जिन्हें Base पॉइंटर के माध्यम से पहुंचा जा सकता है। उदाहरण के लिए:

class Base { 
    virtual void fun(); 
    friend int main(); 
} 
class Derived: public Base { 
    virtual void fun(); 
    virtual void foo(); 
    void bar(); 
} 

केवल Derived::fun() मुख्य से पहुँचा जा सकता है:

int main() { 
    Derived *ptr = new Derived; 
    Base* baseptr = ptr; 
    baseptr->fun(); // ok, calls Derived::fun() 
    baseptr->foo(); // error, no such function in Base 
    ptr->foo(); // error, foo is private 
    return 0; 
} 

ध्यान दें कि virtual समारोह जानबूझकर एक्स्टेंसिबल हैं, और Derived में virtual समारोह के किसी भी ओवरराइड इसका मतलब है कि समारोह Base के माध्यम से कहा जा सकता है सूचक; यह virtual कार्यों का मुख्य उद्देश्य है। यदि Derived इसके ओवरराइडिंग फ़ंक्शन private बनाता है, तो यह अभी भी जागरूक होना चाहिए कि फ़ंक्शन को Base पॉइंटर के माध्यम से एक्सेस किया जा सकता है, क्योंकि virtual फ़ंक्शंस के पीछे यह मुख्य विचार है।

+0

ओओक। लेकिन यह थोड़ा सा खतरनाक नहीं है .. मेरा मतलब है, 'बेस' कक्षा से प्राप्त होने वाले सभी कार्यों के पास उनके निजी सदस्य 'बेस' वर्ग के मित्र कार्यों के लिए सुलभ होंगे। – Haris

+0

@haris, नहीं! केवल 'वर्चुअल' फ़ंक्शंस जो पहले से ही 'बेस' में मौजूद हैं! मैं एक मिनट में जवाब का विस्तार करूंगा। – Petr

+1

@haris, उत्तर – Petr

0

ऐसा इसलिए हो रहा है क्योंकि आपने वर्चुअल के रूप में fun घोषित किया है। रनटाइम पर जब vtable खोजा जाता है, तो यह Derived::fun() के लिए प्रविष्टि पाता है और इसलिए पते पर कूदता है।

हालांकि मित्र कार्यों को विरासत में नहीं मिला है, तो आप इसका उपयोग करके जांच सकते हैं।

class Base { 
private: 
    virtual void fun() { cout << "Base Fun"; } 
    friend int main(); 
    int z = 20; 
}; 

class Derived : public Base { 
private: 
    void fun() { cout << "Derived Fun"; } 
    int m = 10; 
}; 

int main() 
{ 
    Base *ptr = new Derived; 
    ptr->z = 10; //Accepted 
    ptr->m = 5; //error 
    return 0; 
} 

Derivedm के निजी सदस्य मुख्य रूप से सुलभ नहीं है।

+0

मुझे आपको नहीं मिला, कार्यक्रम' मुख्य()' से व्युत्पन्न वर्ग के निजी कार्यों तक पहुंच रहा है। फ़ंक्शन .. बेस क्लास आभासी प्रभावों में 'मजेदार()' फ़ंक्शन कैसे बना रहा है .. – Haris

+0

@ निशांत मुझे संदेह है कि vtables इस तरह से काम करते हैं .. यह विवरण देखें http://imgur.com/6e23Roa – Haris

+0

@DenisZaikin हां, जाहिर है यह "बेस फन" होगा, क्योंकि पीआरटी व्युत्पन्न वस्तु की ओर इशारा कर रहा है, जिसमें आधार का उपनिवेश है। – Nishant

1

Friend कार्य कभी विरासत में भाग नहीं लेते हैं।

यहां क्या हो रहा है?
जब वर्चुअल विधि Base कक्षा में परिभाषित की जाती है, तो वर्चुअल तालिका बनाई जाती है जिसमें funBase वर्ग की विधि शामिल है। और चूंकि, Derived वर्ग को विरासत में मिला है, VTABLE में Derived वर्ग fun विधि का पता भी शामिल है। अब, mainBase वर्ग का मित्र कार्य है, इसलिए संकलक अपने सदस्यों की पहुंच को main विधि तक पहुंच प्रदान करता है, चाहे उनके पहुंच विनिर्देशक हों। इसलिए, mainDerived::fun और Derived वर्ग fun का पता चला जाता है रनटाइम पर कॉल किया जाता है।

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