C++ में निजी फ़ंक्शन के साथ सार्वजनिक वर्चुअल फ़ंक्शन को ओवरराइड करना




override access-control (5)

आप आश्चर्यजनक परिणाम प्राप्त करते हैं कि यदि आपके पास कोई बच्चा है, तो आप फू को नहीं बुला सकते, लेकिन आप उसे आधार पर डाल सकते हैं और फिर फू को कॉल कर सकते हैं।

child *c = new child();
c->foo; // compile error (can't access private member)
static_cast<base *>(c)->foo(); // this is fine, but still calls the implementation in child

मुझे लगता है कि आप ऐसे उदाहरण का अनुपालन करने में सक्षम हो सकते हैं, जहां आप किसी समारोह का खुलासा नहीं करना चाहते हैं, सिवाय इसके कि जब आप इसे बेस क्लास के उदाहरण के रूप में इलाज कर रहे हैं लेकिन यह तथ्य यह है कि उस स्थिति में जो पोजीशन उठता है वह उस रेखा के साथ कहीं खराब ओओ डिज़ाइन का सुझाव देगा जो शायद पुन:

क्या कोई ओवरराइड सी ++ वर्चुअल फ़ंक्शन पर बेस क्लास से अलग अनुमतियाँ बनाने के लिए कोई कारण है? ऐसा करने में कोई खतरा है?

उदाहरण के लिए:

class base {
    public:
        virtual int foo(double) = 0;
}

class child : public base {
    private:
        virtual int foo(double);
}

सी + + अकसर पूछते हैं कि यह एक बुरा विचार है, लेकिन यह क्यों नहीं कहता है

मैंने कुछ कोड में इस मुहावरे को देखा है और मेरा मानना ​​है कि लेखक एक अंतिम धारणा के आधार पर प्रयास कर रहे थे कि एक निजी सदस्य कार्य को ओवरराइड करना संभव नहीं है। हालांकि, यह लेख निजी कार्यों को ओवरराइड करने का एक उदाहरण दिखाता है। बेशक सी + + एफएसी का एक और हिस्सा ऐसा करने की सिफारिश करता है।

मेरे ठोस प्रश्न:

  1. क्या व्युत्पन्न वर्ग बनाम आधार वर्ग में आभासी विधियों के लिए एक अलग अनुमति का उपयोग करने में कोई तकनीकी समस्या है?

  2. क्या ऐसा करने का कोई भी उचित कारण है?


इसमें कोई तकनीकी समस्या नहीं है, लेकिन आप ऐसी स्थिति के साथ समाप्त हो जाएंगे जहां सार्वजनिक रूप से उपलब्ध फ़ंक्शंस इस पर निर्भर करेगा कि आपके पास आधार या व्युत्पन्न सूचक है या नहीं

यह मेरी राय में अजीब और भ्रामक होगा


यह किया जा सकता है, और कभी-कभी लाभों की भी बढ़ोतरी होगी उदाहरण के लिए, हमारे कोडबेस में, हम एक लाइब्रेरी का उपयोग कर रहे हैं जिसमें एक सार्वजनिक फ़ंक्शन वाला क्लास होता है जिसे हम इस्तेमाल करते थे, लेकिन अब अन्य संभावित समस्याओं (कॉल करने के लिए सुरक्षित तरीके हैं) के कारण उपयोग को हतोत्साहित करते हैं। हमारे पास भी उस वर्ग से व्युत्पन्न क्लास होता है जो हमारे बहुत सी कोड सीधे उपयोग करते हैं। इसलिए, हमने दिए गए कार्य को व्युत्पन्न वर्ग में निजी बना दिया ताकि हर किसी को इसका इस्तेमाल न करने में मदद मिल सके, यदि वे इसकी मदद कर सकें। यह इसका उपयोग करने की क्षमता को खत्म नहीं करता है, लेकिन जब कोड कोड समीक्षाओं के बाद कोड को संकलित करने की कोशिश करता है, तब कुछ उपयोग हो जाएगा


  1. कोई तकनीकी समस्या नहीं है, यदि आप तकनीकी द्वारा इसका मतलब है क्योंकि छिपे हुए रनटाइम की लागत होती है
  2. यदि आप सार्वजनिक रूप से आधार प्राप्त करते हैं, तो आपको ऐसा नहीं करना चाहिए। यदि आप संरक्षित या निजी माध्यम से वारदात करते हैं, तो यह ऐसे तरीकों का उपयोग करने में मदद कर सकता है, जो आपके लिए मूल सूचक नहीं है।

निजी विरासत के लिए एक अच्छा उपयोग-मामला एक श्रोता / निरीक्षक घटना इंटरफ़ेस है।

निजी ऑब्जेक्ट के लिए उदाहरण कोड:

class AnimatableListener {
  public:
    virtual void Animate(float delta_time);
};

class BouncyBall : public AnimatableListener {
  public:
    void TossUp() {}
  private:
    void Animate(float delta_time) override { }
};

ऑब्जेक्ट के कुछ उपयोगकर्ता मूल कार्यक्षमता चाहते हैं और कुछ बच्चे की कार्यक्षमता चाहते हैं:

class AnimationList {
   public:
     void AnimateAll() {
       for (auto & animatable : animatables) {
         // Uses the parent functionality.
         animatable->Animate();
       }
     }
   private:
     vector<AnimatableListener*> animatables;
};

class Seal {
  public:
    void Dance() {
      // Uses unique functionality.
      ball->TossUp();
    }
  private:
    BouncyBall* ball;
};

AnimationList इस तरह माता-पिता के लिए एक संदर्भ रख सकती है और माता-पिता की कार्यक्षमता का उपयोग कर सकती है। जबकि Seal बच्चे के लिए एक संदर्भ रखती है और अद्वितीय बच्चे की कार्यक्षमता का उपयोग करती है और माता-पिता की अनदेखी करते हैं इस उदाहरण में, Seal को Animate फोन नहीं करना चाहिए। अब, जैसा कि ऊपर उल्लेख किया गया है, Animate को आधार वस्तु को कास्टिंग करके कहा जा सकता है, लेकिन यह और अधिक कठिन है और आमतौर पर नहीं किया जाना चाहिए।





virtual-functions