संरक्षित तरीकों के लिए वास्तविक दुनिया के परिदृश्य


14

आज मैंने देखा कि मैं मूल रूप protectedसे C ++ कोड में कभी भी विधियों का उपयोग नहीं करता , क्योंकि मुझे शायद ही कभी किसी अभिभावक के गैर-सार्वजनिक तरीकों को कॉल करने की आवश्यकता महसूस होती है। मैं टेम्पलेट पद्धति पैटर्न में जावा में संरक्षित का उपयोग करता हूं, लेकिन चूंकि आप सी ++ में निजी तरीकों को ओवरराइड कर सकते हैं, मुझे protectedवहां भी ज़रूरत नहीं है ।

तो कुछ वास्तविक दुनिया के परिदृश्य क्या हैं जहां मैं protectedC ++ कोड में विधियों का उपयोग करना चाहूंगा ?

(ध्यान दें कि मैं सामान्य रूप से कार्यान्वयन विरासत का बहुत शौकीन नहीं हूं, जो बहुत कुछ समझा सकता है ...)

जवाबों:


12

यहाँ एक उदाहरण है

class Base {
public:
  // other members ...

protected:
  ~Base() { }
};

एक गैर-बहुरूपी आधार वर्ग के रूप में उपयोग किया जाता है। लेकिन उपयोगकर्ताओं को इस delete baseptr;पर कॉल करने की अनुमति नहीं दी जाएगी क्योंकि विध्वंसक दुर्गम है। चूंकि इसमें कोई वर्चुअल विध्वंसक नहीं है, इसलिए लोगों को ऐसा करने की अनुमति दी जाती है जो अपरिभाषित व्यवहार करता है। हर्ब द्वारा "आभासीता" देखें ।


1
क्या आप लोगों के साथ है? इसे क्यों ठुकरा दिया गया? यह पूरी तरह से उचित है। यदि आप इसे नहीं समझते हैं, तो कृपया पूछें। यदि आपको लगता है कि यह गलत है, तो कृपया समझाएं। हम यहां आपकी अंतर्दृष्टि से सीख रहे हैं।
एसबी

क्यों -1 यह पहली चीज है जिसके बारे में मैंने सोचा था।
GManNickG

1
कंस्ट्रक्टर और डिस्ट्रक्टर्स केवल उन उपयोगों के बारे में हैं जिन्हें मैंने देखा है। ध्यान दें कि gcc अभी भी एक चेतावनी का उत्सर्जन करता है कि इस पर विध्वंसक गैर-आभासी है।
मथिउ एम।

+1 मैं कुछ पुस्तकों की सलाह को लागू करने के लिए संरक्षित पद्धति का भी उपयोग करता हूं: सार्वजनिक वर्चुअल फ़ंक्शन के बजाय संरक्षित वर्चुअल फ़ंक्शन के साथ एक सार्वजनिक इंटरफ़ेस है।
क्लेम

3

एक उदाहरण जो मैं अक्सर उपयोग करता हूं वह यह है कि मेरी वस्तु पदानुक्रम के बेस क्लास में मेरे पास एक संरक्षित लकड़हारा होगा। मेरे सभी आधार वर्गों को लॉगर तक पहुंच की आवश्यकता होगी, लेकिन सार्वजनिक रूप से सुलभ होने का कोई कारण नहीं है।

इसके अलावा, यदि आप टेम्पलेट पैटर्न का उपयोग कर रहे हैं, और आपके पास बेस क्लास पर एक पूर्व या पोस्ट निष्पादित विधि है, तो आप आधार कार्यान्वयन को ओवरराइडिंग विधि से कॉल करना चाह सकते हैं। यदि आधार केवल निजी है (और अभी भी C ++ में अधिलेखित किया जा सकता है), तो आप ओवरराइडिंग विधि से आधार कार्यान्वयन को कॉल करने में सक्षम नहीं होंगे।


1
बेस क्लास तरीकों को कॉल नहीं करने के बारे में सभी टेम्पलेट पैटर्न नहीं है ???
एसबी

पॉइंट लिया गया, लेकिन मैं यह नहीं कहूंगा कि बेस क्लास मेथड पर कॉल न करने के बारे में यह 'सब' है। कई स्थितियों में मेरे पास ऑब्जेक्ट पदानुक्रम है जो कई स्तरों वाले टेम्पलेट पैटर्न को लागू करते हैं, जिनमें से प्रत्येक थोड़ा और कार्यक्षमता / चेक जोड़ता है। इन मामलों में, एक संरक्षित तरीका आवश्यक होगा।
bryanatkinson

1

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

class Base
{
private:
    bool m_bInitialized;
public:
    virtual void Initialize() = 0;

    void setInitialized() { m_bInitialized = true; };
    bool isInitialized() const { return m_bInitialized; };
}; // eo class Base

यहां सब ठीक है और अच्छा है। सिवाय जब एक व्युत्पन्न वर्ग setInitialized()कम से कम इस तथ्य को पुकारने की जहमत नहीं उठाता कि कोई भी उसे बुला सकता है (हम इसे यहां संरक्षित कर सकते हैं, और संरक्षित तरीकों का उपयोग करने का एक और कारण!)। मैं एक वर्ग को पसंद करता हूं जो वर्चुअल संरक्षित सदस्यों का उपयोग करता है:

class Base
{
private: 
    bool m_bInitialized;

protected:
    virtual void InitializeImpl() = 0;

public:

    void Initialize()
    {
        InitializeImpl();
        m_bInitialized = true;
    }; // eo Initialize

    bool isInitialized() const { return m_bInitialized; };
}; // eo class Base

हमारे नए वर्ग में, सभी आरंभिकता अभी भी व्युत्पन्न वर्ग को सौंपी गई है। एक अपवाद के रूप में फेंक दिया गया है, हम "यह वर्ग आरम्भिक है" अनुबंध को बनाए रखते हैं जो हमारी विधि कहती है।


0

कई अन्य विशेषताओं के रूप में, protectedआप कुछ विस्तार के लिए इनकैप्सुलेशन को तोड़ने की अनुमति देते हैं। शुद्ध OO अवधारणाओं को तोड़ना आमतौर पर कई कारणों से किया जाता है

  1. बेहतर प्रदर्शन प्राप्त करना (सोचना inline),
  2. कोड को समझना आसान है, और, विडंबना यह है कि,
  3. बेहतर एनकैप्सुलेशन ( friendआपको कुछ मित्रों के वर्ग के सदस्यों तक पहुंच को प्रतिबंधित करने की अनुमति देता है)

और protectedउस बॉक्स में सिर्फ एक टूल है। यदि आप व्युत्पन्न वर्गों को किसी वर्ग के कुछ हिस्सों तक पहुँच देना चाहते हैं, जो आम जनता से छिपाई जानी चाहिए, तो आप इसका उपयोग कर सकते हैं।

एक मामला जहां मैंने इसका उपयोग किया है, वह एक वर्ग के सभी कंस्ट्रक्टरों को बनाने के लिए है protected, मूल रूप से उस वर्ग को अमूर्त बना रहा है (आप इसे व्युत्पन्न नहीं कर सकते हैं सिवाय एक व्युत्पन्न वर्ग के ऑब्जेक्ट के उप-ऑब्जेक्ट के रूप में)।


0

शायद यह खराब डिजाइन था, लेकिन मेरे पास ऐसा कुछ था:

// much simplified, of course
class input_device // base class
{
public:
    virtual ~input_device() {}

    // normally would be private with public caller, etc.
    virtual void update() = 0; 

    template <typename Func>
    void register_callback(Func func)
    {
        mButtonPressSignal.connect(func);
    }

protected:
    void trigger_signal(unsigned button)
    {
        mButtonPressSignal(button);
    }

private:
    boost::signals2::signal<void(unsigned)> mButtonPressSignal;
};

व्युत्पन्न वर्ग, में update(), कॉल करके सिग्नल को ट्रिगर कर सकते हैं trigger_signal()। लेकिन क्योंकि वे सभी संकेत के साथ करने में सक्षम होना चाहिए, संकेत ही निजी छोड़ दिया गया था। ट्रिगर फ़ंक्शन को संरक्षित किया गया था क्योंकि केवल व्युत्पन्न वर्ग इसे ट्रिगर करने में सक्षम होना चाहिए, न कि कुछ भी।


0

"पब्लिक मेथड्स": एक वर्ग ऐसा कर सकता है। "संरक्षित तरीके": एक वर्ग यह कैसे कर सकता है। "निजी तरीके": एक वर्ग यह कैसे कर सकता है, लेकिन "मैं पागल हूं और किसी को यह जानने की इच्छा नहीं है कि मैं यह कैसे करता हूं"।

// burguers.hpp

class BurguerClass {
  private: void addSecretRecipeSauce();  

  protected: virtual void addBread();  
  protected: virtual void addSalad();  
  protected: virtual void addMeat();
  protected: virtual void addExtraIngredients();

  public: virtual void makeBurguer();  
}

class CheeseBurguerClass: public BurguerClass {
  protected: override void addBread();  
  protected: override void addSalad();  
  protected: override void addMeat();
  protected: override void addExtraIngredients();

  protected: virtual void addCheese();

  public: override void makeBurguer();
}

class RanchStyleBurguerClass: public BurguerClass {
  protected: override void addBread();  
  protected: override void addSalad();  
  protected: override void addMeat();
  protected: override void addExtraIngredients();

  public: override void makeBurguer();
}

class EastCoastVegetarianStyleBurguerClass: public BurguerClass {
  protected: override void addBread();  
  protected: override void addSalad();  
  protected: override void addMeat();
  protected: override void addExtraIngredients();

  public: override void makeBurguer();
}

तो, आपके फास्ट फूड रेस्तरां में एक नया रसोइया (डेवलपर) आता है। आप इसे सिखाते हैं, आप बर्गर (सार्वजनिक तरीके) बेचते हैं, कैसे बर्गर (संरक्षित तरीके) तैयार करते हैं, लेकिन अपने आप को "पेटेंट" गुप्त नुस्खा सॉस रखें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.