2012-05-19 5 views
5

मैं निम्नलिखित सेटअप सही पाने के लिए कोशिश कर रहा हूँ की बुला आदेश लागू करने के लिए कैसे करें: (एकाधिक स्रोत फ़ाइलें, संकलन इकाइयों के साथ)विनाशकर्ता

एक दिया आवेदन प्रकार class A कई संकलन इकाइयों में परिभाषित की वैश्विक चर है। इन्हें class B (जहां केवल 1 उदाहरण मौजूद होना चाहिए) को पेश करने के लिए नए द्वारा "प्रबंधित" होना चाहिए, इस अर्थ में कि वे कक्षा बी के उदाहरण पर और "विनाश" पर स्वयं को "पंजीकरण" करते हैं।

कन्स्ट्रक्टर के लिए काम करने के लिए चीज को सेट करना काफी सीधे है। एक का उपयोग कर सकते हैं:

types.h:

class B { 
    static B& Instance() { 
    static B singleton; 
    return singleton; 
    } 
    void registerA(const A& a) { 
    // whatever 
    } 
}; 


class A { 
    A() { B::Instance().registerA(this); } 
}; 

कैसे विनाशकर्ता सही पाने के लिए?

class A { 
    A() { B::Instance().registerA(this); } 
    ~A() { B::Instance().signoffA(this); } 
}; 

तो B का नाशक A का नाशक से पहले कहा जा सकता है: का उपयोग कर सकते हैं। फिर कक्षा A का उदाहरण B के एक नए नव निर्मित उदाहरण पर संकेत देता है।

file1.cc

#include "types.h" 
namespace C { 
    A a; 
} 

file2.cc

#include "types.h" 
namespace C { 
    A b; 
} 

मैं ऐसे कर सकते हैं पर लगता है:

परीक्षण का मामला एक नाम स्थान में class A के उदाहरण की परिभाषा के साथ एक बहु स्रोत फ़ाइल सेटअप होगा बूस्ट स्मार्ट पॉइंटर्स के साथ आसानी से चीज। हालांकि, यदि संभव हो तो मैं निर्भरता को यथासंभव कम रखने के लिए अतिरिक्त पुस्तकालयों का उपयोग करना टालना चाहूंगा।

एक चीज जो मदद कर सकती है: सभी वैश्विक चर नामित नामस्थान में हैं।

+0

कृपया अपना इंडेंटेशन और स्कोपिंग ठीक करें। –

+0

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

+0

ध्यान दें कि 'रजिस्टर' सी ++ और सी में कीवर्ड है, और इस प्रकार आपका कोड संकलित नहीं होता है। –

उत्तर

4

मुझे लगता है कि आप ठीक हैं। यहाँ "समाप्ति" पर 3.6.3 है:

निर्माता या स्थिर भंडारण अवधि के साथ एक वस्तु के गतिशील आरंभीकरण के पूरा होने के एक और की है कि इससे पहले कि अनुक्रम है, तो दूसरे के नाशक के पूरा होने से पहले अनुक्रम है पहले के विनाशक की शुरुआत।

मान लीजिए आप निम्नलिखित सेटअप:

struct A; 

struct B 
{ 
    static B & get() { static B impl; return impl; } 
    void registrate(A *); 

private: 
    B() { /* complex stuff */ } 
    // ... 
}; 

struct A { A() { B::get().registrate(this); } }; 

A a1; 

अब जो कुछ भी होता है, एक स्थिर A प्रकार वस्तु के पहले निर्माता B::get() है, जो पूरा होने से पहले स्थिर impl वस्तु के निर्माण के अनुक्रम कॉल करेंगे पहले A -कॉन्स्ट्रक्टर का। उपर्युक्त खंड से, यह गारंटी देता है कि B impl -object के विनाशक के बाद सभी A -destructors अनुक्रमित हैं।

+0

क्या उद्धृत विवरण उस मामले का संदर्भ नहीं देता है जहां दोनों ऑब्जेक्ट स्थिर संग्रहण अवधि के हैं? मेरे मामले में केवल एक 'स्थिर' है। – ritter

+0

मुझे यह नहीं मिला: .. "एक स्थिर ए-प्रकार का पहला कन्स्ट्रक्टर"। 'ए 'स्थिर नहीं है। – ritter

+0

@ फ्रैंक: "स्थिर" का मतलब यह नहीं है कि आप क्या सोचते हैं। उदाहरण में सब कुछ स्थिर भंडारण अवधि है। कीवर्ड 'स्थिर' स्थिर भंडारण अवधि के साथ ऑब्जेक्ट बनाने के कई तरीकों में से एक है। –

2

B उदाहरण स्थैतिक है, इसलिए यह B सिंगलटन के निर्माण के बाद बनाए गए किसी भी A इंस्टेंस को बाहर कर देगा।

+0

यह निश्चित रूप से सच है यदि सभी ऑब्जेक्ट एक ही संकलन इकाई में हैं। यहां ऐसा मामला नहीं है। मुझे यकीन नहीं है कि 'स्थिर' ऑब्जेक्ट विनाश संकलन इकाइयों में भी स्थगित हो गया है – ritter

+0

@ फ्रैंक मैं नहीं देख सकता कि यह संकलन इकाइयों में कैसे लागू नहीं होगा। – juanchopanza

+0

हां, सेटअप ठीक है। लेकिन कारण रचनाकारों और तथ्य यह है कि यह स्थिर है। यदि आप दोनों परिस्थितियों का एक ही समय में मतलब रखते हैं, तो आप सही हैं – ritter

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