2016-09-05 13 views
5

हाल ही में मैं इतना एक वर्ग जो अलग कार्यक्षमता है कि यह है चाहिए, आदर्श का एक सा ले के उपयोग के बारे में एक प्रश्न पोस्ट। मुझे सिंगलटन पैटर्न के बारे में जानने की अनुशंसा की गई थी ताकि कक्षा का केवल एक उदाहरण बनाया जा सके और यह उस डेटा के चारों ओर घूमने वाले संचालन के सेट को प्रबंधित करता है जो इसे समाहित करता है। आप यहां प्रश्न देख सकते हैं - using Static Container for base and derived classesनामस्थान का उपयोग कर के बजाय एकमात्र


अब इस कोड पर विचार -

#include <iostream> 
#include <string> 
#include <unordered_map> 

class A{ 
    std::string id; 
    public: 
    A(std::string _i): id(_i){} 
    virtual void doSomething(){std::cout << "DoSomethingBase\n";} 
}; 

class B : public A{ 
    std::string name; 
    public: 
    B(std::string _n):name(_n), A(_n){} 
    void doSomething(){std::cout << "DoSomethingDerived\n";} 
}; 

namespace ListA{ 
    namespace{ 
     std::unordered_map<std::string, A*> list; 
    } 
    void init(){ 
     list.clear(); 
    } 
    void place(std::string _n, A* a){ 
     list[_n] = a; 
    } 
} 


int main() { 
    ListA::init(); 
    ListA::place("b1", new B("b1")); 
    ListA::place("a1", new A("a1")); 
    return 0; 
} 

तथ्य यह है कि मैं अभी भी कच्चे संकेत दिए गए जो स्मृति लीक कर रहे हैं कार्यक्रम के रूप में यह है समाप्त हो जाता है नहीं है का उपयोग कर रहा अनदेखी कर, यह एक अच्छा है वैश्विक स्थैतिक चर, या एक सिंगलटन का उपयोग करने के विकल्प?


पिछले प्रश्न के संबंध में, मैं कक्षा ए (आधार वर्ग) और वर्ग बी (व्युत्पन्न वर्ग) एक namespace है कि इन वस्तुओं की एक सूची का प्रबंधन स्वतंत्र पुनर्गठित किया है। तो क्या यह एक अच्छा विचार है, या एक पूरी तरह से बुरा अभ्यास है? क्या इसके लिए कोई कमी है?

एक अच्छा सिंगलटन कार्यान्वयन मैं सुझाव दिया गया था इस प्रकार थी -

class EmployeeManager 
{ 
    public: 
     static EmployeeManager& getInstance() 
     { 
      static EmployeeManager instance; // Guaranteed to be destroyed. 
            // Instantiated on first use. 
      return instance; 
     } 
    private: 
     EmployeeManager() {}; 
     std::unordered_map<std::string, Employee&> list; 
    public: 
     EmployeeManager(EmployeeManager const&) = delete; 
     void operator=(const&) = delete; 
     void place(const std::string &id, Employee &emp){ 
      list[id] = emp; 
     } 
}; 

class Employee 
{ 
    public: 
     virtual void doSomething() = 0; 
}; 

class Writer : public Employee 
{ 
    private: 
     std::string name_; 
    public: 
     Writer(std::string name) : name_(name) {}; 
     void doSomething() { }; 
}; 

ईमानदारी से मैं सिंगलटन पैटर्न और मैं दूर शर्मा कर रहा हूँ कभी नहीं आज़माया यह सीधे उपयोग करने के लिए के बाद से मैं कोई पूर्व अनुभव है और मैं पहले इसे अपने पालतू परियोजनाओं में उपयोग करना चाहूंगा।

+6

किसी सिंगलटन पैटर्न की सिफारिश करने के लिए आपकी प्रतिक्रिया की तरह जब तुम सिर्फ कोई है जो आप पोकर के कुछ दौर एक धुएँ के रंग वापस कमरे में और बाद ले रहा है पता चलता है कि "हम इसे दिलचस्प बनाना चाहिए" मिलने चाहिए। –

+2

सिंगलटन पैटर्न उपयोगकर्ता को केवल एक उदाहरण बनाने के लिए * बल * करने का एक तरीका है। क्या आपको वास्तव में केवल एक की आवश्यकता होने पर कई उदाहरण बनाने का आग्रह होता है? यदि नहीं, तो बस अपनी इच्छित वस्तु बनाएं और इसके साथ किया जाए! –

+0

@ बॉपरसन क्या मुझे वास्तव में मेरे उपयोग के मामले के लिए एक वस्तु बनाने की ज़रूरत है? क्या मुझे बस कुछ संबंधित विशेष कार्यों के साथ std :: मानचित्र की आवश्यकता नहीं है? –

उत्तर

2

क्या यह वैश्विक स्थैतिक चर या एकलटन का उपयोग करने का एक अच्छा विकल्प है?

नहीं, क्योंकि आपको एक और समस्या आ सकती है: static initialization order fiasco। इसे ठीक करने के तरीके हैं - लेकिन स्थैतिक चर के साथ कार्यों के साथ - जो सिंगलेट्स की तरह दिखता है।

... लेकिन तुम क्यों एक वैश्विक चर (नामस्थान में भी) या एकमात्र ज़रूरत है? आप पहली बार उदाहरण में, यह बिल्कुल ठीक है, तो namespace ListA के बजाय आप struct ListA था होगा - प्लस कि namespace{ को हटा दें। फिर आपके पास है:

int main() { 
    ListA list; 
    list.init(); 
    list.place("b1", new B("b1")); 
    list.place("a1", new A("a1")); 
} 

और यह ठीक दिखता है।

फिर आपके सिंगलटन एप्रोच, एक बार फिर - इसके लिए कोई आवश्यकता नहीं है - यदि आप इसे किसी अन्य वर्ग में उपयोग करने की ज़रूरत है, तो इसे संदर्भ या सूचक द्वारा पास करें, तो अपने मुख्य कार्य में EmployeeManager टाइप करें।

+0

मुझे नहीं पता, हर किसी ने मुझे अधिकतम पर केवल एक वस्तु रखने के लिए कहा था। शायद क्योंकि दो या दो से अधिक घोषित होने पर यह बग का कारण बन सकता है? tbh idk:/ –

+0

अभी भी मुझे पूछने की ज़रूरत है, मेरे उदाहरण में यदि मेरे पास ah और a.cpp जैसी पारंपरिक फ़ाइलें हैं, समान रूप से bh और b.cpp के लिए और फिर ListA नामस्थान के साथ एक और ListA.cpp और उपरोक्त कोड का उपयोग करें, तो कैसे होगा 'स्थिर प्रारंभिक आदेश fiasco' भी होता है? वे एक-दूसरे से स्वतंत्र हैं और ListA.cpp केवल कुछ फ़ंक्शंस और एक चर को प्रदान करने के लिए प्रदान कर रहा है:/ –

+0

समस्या तब होगी जब आप मुख्य से पहले अपने वैश्विक वर्ग के उदाहरणों को प्राप्त करने का प्रयास करेंगे (उदाहरण के लिए एक निर्माता के अंदर) निष्पादित हो जाता है। आपका नमूना कोड इससे पीड़ित नहीं है। – marcinj

0

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

+2

क्या आप कुछ और विस्तार कर सकते हैं - "मूल्यों/संदर्भ का प्रचार करना चाहिए (वास्तव में यह बड़े रखरखाव सिस्टम के लिए किया जाना चाहिए) जिसमें ऑब्जेक्ट को अपने बच्चे, एक पर्यवेक्षक/घटना प्रणाली या एक ईवेंट/संदेश बस से गुजरने के संदर्भ में होना चाहिए । " छोटे उदाहरण मेरे लिए अच्छा प्रदर्शन करेंगे। –

1

मुझे यकीन है कि अगर आप पहले से ही जानते हैं कि नहीं कर रहा हूँ, लेकिन आप याद रखना होगा कि सिंगलटन वास्तव में आलसी आरंभीकरण के साथ एक वैश्विक चर रहा है की जरूरत है।

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

स्थिर वस्तु बस पल में प्रारंभ जब यह पहले बनाया जा करने की जरूरत है के लिए प्रकट होता है - लेकिन जब इस समय वास्तव में है, अपरिभाषित है कम से कम C++।

आप स्थैतिक प्रारंभिकरण के साथ आलसी प्रारंभिकता को प्रतिस्थापित कर सकते हैं, लेकिन आपको किसी भी तरह से यह सुनिश्चित करना होगा कि प्रारंभिक क्रम में प्रारंभिकरण होता है।

नामस्थान के अंदर परिभाषित चर कुछ वैश्विक स्तर पर चर घोषित करने के अलावा कुछ और नहीं है। नेमस्पेस खुले हैं, नेमस्पेस के अंदर नियम प्रतीक संकल्प को छोड़कर, नामस्थान के बाहर समान हैं।

क्या आप आदेश दिया आरंभीकरण लागू करने के लिए क्या कर सकते हैं अंदर सभी निर्भर वैश्विक वस्तुओं के साथ एक वैश्विक चर बनाने के लिए, struct के रूप में है कि सभी उन्हें जैसे क्षेत्रों में शामिल होंगे है (नहीं स्थिर क्षेत्रों!)। ध्यान दें कि प्रारंभिकरण का सटीक क्रम केवल उस संरचना के क्षेत्र होने वाली वस्तुओं के बीच सुनिश्चित किया जाएगा, न कि उनके और किसी अन्य वैश्विक वस्तुओं के बीच।

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