2009-03-10 18 views

उत्तर

139

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

उदाहरण के लिए, यदि आप कुछ प्रकार की संदर्भ गिनती चीज कर रहे हैं, तो आप ऑब्जेक्ट (या प्रबंधक जो "दोस्त" एड) हो सकते हैं, संदर्भों की संख्या गिनने के लिए जिम्मेदार हो सकते हैं और संख्या को हटा सकते हैं शून्य हिट करता है। एक निजी डॉटर किसी और को इसे हटाने से रोक देगा जब इसके संदर्भ में अभी भी संदर्भ थे।

एक और उदाहरण के लिए, यदि आपके पास कोई ऑब्जेक्ट है जिसमें एक प्रबंधक (या स्वयं) है जो इसे नष्ट कर सकता है या प्रोग्राम में अन्य स्थितियों के आधार पर इसे नष्ट करने में कमी कर सकता है, जैसे डेटाबेस कनेक्शन खुला या फ़ाइल लिखा जा रहा है। आपके पास कक्षा या प्रबंधक में "request_delete" विधि हो सकती है जो उस स्थिति की जांच करेगी और यह या तो हटा या अस्वीकार कर देगी, और यह बताएगी कि उसने क्या किया है। यह बहुत अधिक लचीला है कि सिर्फ "हटाएं" को बुला रहा है।

+3

देख guidline # 4 http://www.gotw.ca/publications/mill18.htm – Eric

+2

यह aswer कुछ कोड उदाहरण याद आ रही। – mrgloom

43

जब आप नहीं चाहते हैं कि उपयोगकर्ता विनाशक का उपयोग करें, यानी, आप चाहते हैं कि वस्तु केवल अन्य माध्यमों से नष्ट हो।

http://blogs.msdn.com/larryosterman/archive/2005/07/01/434684.aspx एक उदाहरण देता है, जहां ऑब्जेक्ट संदर्भ गिना जाता है और केवल शून्य पर जाने पर ऑब्जेक्ट द्वारा ही नष्ट किया जाना चाहिए।

5

कक्षा केवल ही हटा दी जा सकती है। उपयोगी अगर आप संदर्भ गिनती वस्तु का कुछ प्रयास कर रहे हैं। फिर केवल रिलीज विधि ऑब्जेक्ट को हटा सकती है, संभवतः आपको त्रुटियों से बचने में मदद करती है।

55

ऐसी वस्तु को ढेर पर कभी नहीं बनाया जा सकता है। हमेशा ढेर पर। और किसी मित्र या सदस्य के माध्यम से हटाना होगा। एक उत्पाद एक ऑब्जेक्ट पदानुक्रम और कस्टम मेमोरी-मैनेजर का उपयोग कर सकता है - ऐसे परिदृश्य एक निजी dtor का उपयोग कर सकते हैं।

#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; 
} 
+1

किसी मित्र/या सदस्य/ – MSalters

+0

के माध्यम से हटाना है, यह पहले से ही उल्लेख किया गया था - इसलिए मैंने इसे छोड़ दिया। अपडेटटाटा (मेरे कथन को पढ़ने पर दूसरा थोड़ा मजबूत दिखता है)। – dirkgently

+12

सुधार: इस तरह की एक वस्तु * स्टैक पर बनाई जा सकती है (लेकिन केवल एक दोस्त या खुद के दायरे में)। –

2

यह Windows में समस्या जहां प्रत्येक मॉड्यूल ऐसे Debug ढेर के रूप में एक अलग ढेर, उपयोग कर सकते हैं के साथ सौदा करने के लिए एक रास्ता हो सकता है। यदि उस समस्या को सही ढंग से संभाला नहीं जाता है badthings हो सकता है।

3

मुझे पता है कि आप निजी विनाशक के बारे में पूछ रहे थे। यहां बताया गया है कि मैं संरक्षित लोगों का उपयोग कैसे करता हूं। विचार यह है कि आप मुख्य वर्ग को पॉइंटर के माध्यम से कक्षा में हटाना नहीं चाहते हैं जो मुख्य को अतिरिक्त कार्यक्षमता जोड़ता है।
नीचे दिए गए उदाहरण में मैं नहीं चाहता कि GuiWindow को हैंडलरहोल्डर पॉइंटर के माध्यम से हटा दिया जाए।

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(){} 
}; 
15

COM उदाहरण को हटाने के लिए इस रणनीति का उपयोग करता है। COM विनाशक को निजी बनाता है और उदाहरण को हटाने के लिए एक इंटरफ़ेस प्रदान करता है।

यहां एक उदाहरण है कि एक रिलीज विधि कैसा दिखाई देगी।

int MyRefCountedObject::Release() 
{ 
_refCount--; 
if (0 == _refCount) 
{ 
    delete this; 
    return 0; 
} 
return _refCount; 
} 

ATL COM ऑब्जेक्ट इस पद्धति का एक प्रमुख उदाहरण हैं।

+0

निर्देशक। धन्यवाद! –

3

dirkgently गलत है। यहां स्टैक पर बनाए गए निजी सी-टोर और डी-टोर के साथ ऑब्जेक्ट का एक उदाहरण दिया गया है (मैं यहां स्थिर सदस्य फ़ंक्शन का उपयोग कर रहा हूं, लेकिन यह मित्र फ़ंक्शन या मित्र वर्ग के साथ भी किया जा सकता है)।PrivateCD :: Tryme, p._i = 8

+2

मुझे यकीन है कि स्पष्ट रूप से मतलब है कि कोड * * आपकी कक्षा का उपयोग करता है, कक्षा को स्टैक पर तुरंत चालू नहीं कर सकता है। निस्संदेह आप क्लास * कक्षाओं के भीतर * स्टैक पर कक्षा को तुरंत चालू कर सकते हैं, क्योंकि उस संदर्भ में आप निजी memebers तक पहुंच सकते हैं। –

5

यहाँ जवाब पहले से ही मौजूद करने के लिए जोड़ा जा रहा है अंदर ;:

#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); 
}; 

इस कोड को उत्पादन का उत्पादन होगा factory को लागू करते समय निजी रचनाकार और विनाशक काफी उपयोगी होते हैं जहां बनाई गई वस्तुओं को ढेर पर आवंटित करने की आवश्यकता होती है। वस्तुओं को सामान्य रूप से स्थिर सदस्य या मित्र द्वारा बनाया/हटाया जाएगा। विशिष्ट उपयोग का उदाहरण:

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 
}