जवाबों:
मूल रूप से, किसी भी समय आप चाहते हैं कि आपकी कक्षा की वस्तुओं के जीवन चक्र के लिए कोई अन्य वर्ग जिम्मेदार हो, या आपके पास किसी वस्तु के विनाश को रोकने का कारण हो, तो आप विध्वंसक को निजी बना सकते हैं।
उदाहरण के लिए, यदि आप किसी प्रकार की रेफरेंस काउंटिंग चीज़ कर रहे हैं, तो आपके पास रेफ़रेंस की संख्या गिनने के लिए ज़िम्मेदार वस्तु (या प्रबंधक जो "मित्र" एड है) हो सकता है और नंबर के हिट होने पर उसे डिलीट कर सकता है। एक निजी डोर किसी अन्य व्यक्ति को इसे हटाने से तब रोकेगा जब इसके संदर्भ अभी भी थे।
एक अन्य उदाहरण के लिए, क्या होगा यदि आपके पास एक ऑब्जेक्ट है जिसमें एक प्रबंधक (या स्वयं) है जो इसे नष्ट कर सकता है या कार्यक्रम में अन्य शर्तों के आधार पर इसे नष्ट करने के लिए अस्वीकार कर सकता है, जैसे कि डेटाबेस कनेक्शन खुला होना या एक फ़ाइल लिखा जा रहा है। आपके पास कक्षा में "request_delete" विधि हो सकती है या प्रबंधक उस स्थिति की जांच करेगा और यह या तो हटा देगा या अस्वीकार कर देगा, और एक स्थिति बताएगा जो आपने किया था। यह कहीं अधिक लचीला है कि बस "हटाएं" कॉल कर रहा है।
इस तरह के ऑब्जेक्ट को स्टैक पर कभी नहीं बनाया जा सकता है। हमेशा ढेर पर। और विलोपन किसी मित्र या सदस्य के माध्यम से किया जाना है। एक उत्पाद एकल ऑब्जेक्ट पदानुक्रम और एक कस्टम मेमोरी-मैनेजर का उपयोग कर सकता है - ऐसे परिदृश्य एक निजी डोर का उपयोग कर सकते हैं।
#include <iostream>
class a {
~a() {}
friend void delete_a(a* p);
};
void delete_a(a* p) {
delete p;
}
int main()
{
a *p = new a;
delete_a(p);
return 0;
}
जब आप चाहते हैं कि उपयोगकर्ता विध्वंसक तक न पहुंचें, यानी आप चाहते हैं कि वस्तु केवल अन्य माध्यमों से नष्ट हो जाए।
http://blogs.msdn.com/larryosterman/archive/2005/07/01/434684.aspx एक उदाहरण देता है, जहाँ ऑब्जेक्ट को काउंट किया गया संदर्भ होता है और केवल शून्य द्वारा काउंट होने पर ऑब्जेक्ट को ही नष्ट कर देना चाहिए।
उदाहरण को हटाने के लिए COM इस रणनीति का उपयोग करता है। COM विध्वंसक को निजी बनाता है और उदाहरण को हटाने के लिए एक इंटरफ़ेस प्रदान करता है।
यहाँ एक उदाहरण है कि रिलीज़ विधि क्या दिखती है।
int MyRefCountedObject::Release()
{
_refCount--;
if ( 0 == _refCount )
{
delete this;
return 0;
}
return _refCount;
}
ATL COM ऑब्जेक्ट इस पैटर्न का एक प्रमुख उदाहरण है।
यहां पहले से मौजूद उत्तरों को जोड़ना; निजी निर्माणकर्ता और विध्वंसक एक कारखाने को लागू करते समय काफी उपयोगी होते हैं जहां निर्मित वस्तुओं को ढेर पर आवंटित करने की आवश्यकता होती है। सामान्य रूप से, वस्तुओं को स्थिर सदस्य या मित्र द्वारा बनाया / हटाया जा सकता है। एक विशिष्ट उपयोग का उदाहरण:
class myclass
{
public:
static myclass* create(/* args */) // Factory
{
return new myclass(/* args */);
}
static void destroy(myclass* ptr)
{
delete ptr;
}
private:
myclass(/* args */) { ... } // Private CTOR and DTOR
~myclass() { ... } //
}
int main ()
{
myclass m; // error: ctor and dtor are private
myclass* mp = new myclass (..); // error: private ctor
myclass* mp = myclass::create(..); // OK
delete mp; // error: private dtor
myclass::destroy(mp); // OK
}
कक्षा को केवल स्वयं ही हटाया जा सकता है। उपयोगी यदि आप संदर्भ की कुछ कोशिश कर रहे हैं गिनती की गई वस्तु। तब केवल रिलीज़ विधि ऑब्जेक्ट को हटा सकती है, संभवतः त्रुटियों से बचने में आपकी मदद कर सकती है।
मुझे पता है कि आप निजी विध्वंसक के बारे में पूछ रहे थे। यहां बताया गया है कि मैं कैसे संरक्षित लोगों का उपयोग करता हूं। विचार यह है कि आप पॉइंटर के माध्यम से मुख्य वर्ग को हटाना नहीं चाहते हैं जो मुख्य में अतिरिक्त कार्यक्षमता जोड़ता है।
नीचे दिए गए उदाहरण में मैं नहीं चाहता कि एक हैंडलरहॉल्डर पॉइंटर के माध्यम से गाइविन्डो को हटा दिया जाए।
class Handler
{
public:
virtual void onClose() = 0;
protected:
virtual ~Handler();
};
class HandlerHolder
{
public:
void setHandler( Handler* );
Handler* getHandler() const;
protected:
~HandlerHolder(){}
private:
Handler* handler_;
};
class GuiWindow : public HandlerHolder
{
public:
void finish()
{
getHandler()->onClose();
}
virtual ~GuiWindow(){}
};
dirkgently गलत है। यहां निजी सी-टॉर और स्टैक पर बनाए गए डी-टोर के साथ ऑब्जेक्ट का एक उदाहरण है (मैं यहां स्थैतिक सदस्य फ़ंक्शन का उपयोग कर रहा हूं, लेकिन यह मित्र फ़ंक्शन या मित्र वर्ग के साथ भी किया जा सकता है)।
#include <iostream>
class PrivateCD
{
private:
PrivateCD(int i) : _i(i) {};
~PrivateCD(){};
int _i;
public:
static void TryMe(int i)
{
PrivateCD p(i);
cout << "inside PrivateCD::TryMe, p._i = " << p._i << endl;
};
};
int main()
{
PrivateCD::TryMe(8);
};
यह कोड आउटपुट का उत्पादन करेगा: PrivateCD के अंदर :: TryMe, p._i = 8