2009-06-23 13 views
6

मैं एक एम्बेडेड वातावरण (Arduino/AVR ATMega328) में काम कर रहा हूं और सी ++ में फैक्टरी विधि पैटर्न को कार्यान्वित करना चाहता हूं। हालांकि, मैं जिस कंपाइलर का उपयोग कर रहा हूं (avr-gcc) new कीवर्ड का समर्थन नहीं करता है। new का उपयोग किए बिना इस पैटर्न को लागू करने का कोई तरीका है?क्या मैं नए उपयोग किए बिना सी ++ में फैक्टरी विधि पैटर्न को कार्यान्वित कर सकता हूं?

+2

आप स्मृति आवंटित कैसे करते हैं? डी: – GManNickG

+2

इसके अलावा, क्या यह प्लेसमेंट को नया समर्थन देता है? सबसे अच्छा मैं सोच सकता हूं कि स्थिर रूप से स्मृति का एक हिस्सा आवंटित किया जा रहा है, तो आप प्लेसमेंट-नई कुछ भी कर सकते हैं। – GManNickG

+2

मेमोरी या तो स्टैक (स्टैक-आधारित ऑब्जेक्ट निर्माण सहित) या मॉलोक() के साथ आवंटित की जाती है - जो ऑब्जेक्ट निर्माण का समर्थन नहीं करती है। प्लेसमेंट नया समर्थित नहीं है ... –

उत्तर

7

चूंकि एवीआर कंपाइलर जीसीसी कंपाइलर पर आधारित है, इसलिए यह नए कीवर्ड का समर्थन करने की संभावना है। आपको जो त्रुटि मिल रही है वह वास्तव में क्या है। मैं अनुमान लगा रहा हूं कि यह एक अपरिभाषित फ़ंक्शन, अर्थात् ऑपरेटर नया की लाइनों के साथ एक लिंक/कंपाइलर त्रुटि है। नए ऑपरेटर और ऑपरेटर के बीच एक अंतर है, पहला ऑब्जेक्ट बनाने के लिए प्रयोग किया जाता है और बाद में वस्तुओं के लिए स्मृति आवंटित करने के लिए उपयोग किया जाता है। नया ऑपरेटर ऑपरेटर को ऑब्जेक्ट के प्रकार के लिए नए कहते हैं, फिर ऑब्जेक्ट की वी-टेबल शुरू करता है और ऑब्जेक्ट के कन्स्ट्रक्टर को कॉल करता है। Reading this FAQ यह कहता है कि ऑपरेटर को मानक पुस्तकालयों में परिभाषित नहीं किया गया है।

void *operator new (size_t size) 
{ 
    return some allocated memory big enough to hold size bytes 
} 

और आप एक साथ ही हटाना निर्धारित करने होंगे: आवंटन

void operator delete (void *memory) 
{ 
    free the memory 
} 

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

+0

+1 - मैं इसे ताल के उत्तर के साथ संयोजित करने जा रहा हूं और इसे जाने देता हूं। –

0

क्या आप मॉलोक कर सकते हैं? यदि ऐसा है तो आप अपनी वस्तु को इस तरह से मॉलोक कर सकते हैं।

आपके ऑब्जेक्ट्स की प्रकृति क्या है जिसे आप फैक्ट्री से बनाना चाहते हैं?

  • क्या वे अपरिवर्तनीय हैं?
  • क्या फैक्ट्री का उद्देश्य केवल वस्तुओं के सीमित सेट का उत्पादन करना है जिसे संकलित समय पर जाना जा सकता है?

यदि उत्तर दोनों प्रश्नों के लिए हाँ है, तो आप स्थिर रूप से अपरिवर्तनीय वस्तुओं के अपने सेट के लिए स्मृति आवंटित कर सकते हैं और फ़ैक्टरी विधि को उचित ऑब्जेक्ट पर लौटने की अनुमति दे सकते हैं।

यदि उत्तर किसी भी प्रश्न के लिए नहीं है तो यह काम नहीं करेगा। इस दृष्टिकोण को भी समझें कि आपको हमेशा उस स्मृति को आवंटित करने की समस्या है।

3

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

1

इस तरह कुछ के बारे में क्या?

MyClass *objp = (MyClass*)malloc(sizeof(MyClass)); 
*objp = MyClass(); // or any other c'tor 

संपादित करें: उल्लेख करने के लिए भूल तो वह मान लेता MyClass एक असाइनमेंट ऑपरेटर है।

EDIT2: एक और चीज जिसे मैं भूल गया - हाँ, एक गॉचा है (यह सी ++ है, हमेशा मिलते हैं)। ऑब्जेक्ट के लिए आपको मैन्युअल रूप से डीओ टोर को कॉल करना होगा, क्योंकि आप मुफ्त में उपयोग नहीं कर सकते हैं।

+0

कम से कम यह वीसी ++ 7 में काम करता है। – sharptooth

+1

मेरी मां ने मुझे हमेशा एक सी ++ ऑब्जेक्ट को चालू करने के लिए malloc() का उपयोग करने के बारे में चेतावनी दी। भले ही आप कन्स्ट्रक्टर को कॉल कर रहे हैं और आवंटित मेमोरी में अपना डेटा कॉपी कर रहे हैं, क्या इस दृष्टिकोण के साथ कोई गठिया है? –

+1

हां, स्पष्ट गॉथैस हैं: मेमोरी ब्लॉक अनियंत्रित है और इसलिए असाइनमेंट ऑपरेटर को तदनुसार प्रतिक्रिया करनी चाहिए - यदि यह "प्रारंभिक" सूचक सदस्य को देखता है तो उसे इसे मुक्त करने की कोशिश नहीं करनी चाहिए क्योंकि इसमें कचरा होता है और यह लटक रहा है। मुझे लगता है कि इससे बचने के लिए शून्य-प्रारंभिक मेमोरी ब्लॉक प्राप्त करने के लिए केवल कॉलोक() को कॉल करना सबसे अच्छा है। – sharptooth

0

यदि आप कारखाने का उपयोग कर रहे हैं तो इसका मतलब है कि आप कुछ गतिशील बाध्यकारी व्यवहार चाहते हैं जो इंगित करता है कि आपके पास कुछ वर्चुअल फ़ंक्शन हैं। हालांकि, मॉलोक() का उपयोग कर ऑब्जेक्ट के लिए मेमोरी आवंटित करना संभव हो सकता है (वर्ग का vtable ठीक से सेटअप नहीं किया जाएगा और इसलिए वर्चुअल फ़ंक्शंस को कॉल क्रैश हो जाएगा। जब गतिशील बाध्यकारी की आवश्यकता होती है तो मुझे ऐसा करने का कोई तरीका नहीं दिखता है।

+0

इसे चारों ओर काम किया जा सकता है - स्टैक पर ऑब्जेक्ट आवंटित करें और vtable पॉइंटर के लिए memcpy को कॉल करें ताकि इसे नए ढेर-आवंटित ऑब्जेक्ट पर कॉपी किया जा सके। – sharptooth

+0

तो क्या आप कह रहे हैं कि ताल का जवाब (http://stackoverflow.com/questions/1031301/can-i-implement-the-factory-method-pattern-in-c-without-using-new/1031375#1031375) जीता काम नहीं करते? –

+0

मैंने कोशिश नहीं की है। लेकिन मेरे अनुसार यह काम नहीं करेगा। हालांकि, sharptooth द्वारा सुझाया गया कामकाज काम कर सकता है। – Naveen

0

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

// Class File --------------------------------------------------- 
class MyObject { 
    public: 
     MyObject* getObject(); 

    private: 
     const int MAX_POSSIBLE_COUNT_OF_OBJECTS = 10; 
     static MyObject allocatedObjects[MAX_POSSIBLE_COUNT_OF_OBJECTS]; 

     static allocatedObjectIndex = 0; 
}; 

// Implementation File ------------------------------------------ 

// Instantiate a static array of your objects. 
static MyObject::allocatedObject[MAX_POSSIBLE_COUNT_OF_OBJECTS]; 

// Your method to return already created objects. 
MyObject* MyObject::getObject() { 

    if (allocatedObjectIndex < (MAX_POSSIBLE_COUNT_OF_OBJECTS - 1)) { 
     return allocatedObjects[allocatedObjectIndex++]; 
    } else { 
     // Log error if possible 
     return NULL; 
    } 
} 

कृपया आगाह किया जाए। यह सब स्मृति से है क्योंकि मैंने 8 महीनों में कोई सी ++ नहीं लिखा है।

यह भी ध्यान दें: इसमें गंभीर कमी है कि आप संकलन समय पर रैम का एक गुच्छा आवंटित कर रहे हैं।

+0

आप एक MyObject :: ऑपरेटर को नया (size_t) परिभाषित कर सकते हैं जो उपर्युक्त सभी करता है, यानी पूर्व-आवंटित सरणी का उपयोग करता है, जबकि कुछ गैर मानक के बजाय परिचित नए MyObject (args) वाक्यविन्यास को रखते हुए। इस तरह, आप वस्तुओं का सही ढंग से निर्माण और विनाश कर सकते हैं। – Skizz

+3

एक एम्बेडेड सिस्टम में, मैं संकलन समय पर आरएएन का एक समूह आवंटित करने का सम्मान करता हूं, एक अच्छा बात नहीं, –

3

फैक्टरी विधि की बड़ी तस्वीर वस्तु निर्माण है, जिसका अर्थ है स्मृति मेकअप खपत। एक एम्बेडेड सिस्टम पर, आप रैम से बाध्य हैं और आपके सभी डिज़ाइन निर्णयों को आपकी स्मृति सीमाओं के साथ दिमाग में रखने की आवश्यकता है। ATmega328 में केवल 2 केबी रैम है। मैं इस तरह के एक तंग जगह में गतिशील आवंटित स्मृति का उपयोग करने के खिलाफ सिफारिश करेंगे।

आपकी समस्या को और अधिक विस्तार से जानने के बिना, मैं कक्षा के कुछ उदाहरणों को स्थिर रूप से घोषित करने और कुछ मामलों में उन उदाहरणों का पुन: उपयोग करने की अनुशंसा करता हूं। इसका मतलब है कि आपको यह जानने की जरूरत है कि आपकी वस्तुओं कब और क्यों बनाई गई हैं और - महत्वपूर्ण के रूप में - कब और क्यों वे समाप्त होते हैं; तो आपको यह पता लगाने की आवश्यकता है कि आपको एक समय में कितने सक्रिय होने की आवश्यकता है और एक समय में सक्रिय होना कितना संभव है।

!! डीन

+0

कोई नहीं क्योंकि सभी के पास 2 केबी या रैम का मतलब यह नहीं है कि आप गतिशील स्मृति आवंटन नहीं कर सकते हैं। आप बस इतना आवंटित नहीं कर सकते हैं। आप वहां 500 दो बाइट ऑब्जेक्ट प्राप्त कर सकते हैं (500 * (आवंटन जानकारी के लिए ऑब्जेक्ट + 2 के लिए 2) = 2000)। – Skizz

+0

स्कीज, आपके पहले दो वाक्य सही हैं, लेकिन तीसरा एक उचित नहीं है। 2 केबी रैम (2048 बाइट्स) दोनों सी ढेर और ढेर दोनों रखती है; तो उसके पास केवल उसके सी स्टैक (अनुचित) के लिए 48 बाइट होंगे। एक कार्यक्रम जिसे फैक्ट्री विधि की आवश्यकता होती है वह एक साधारण नहीं है, इसलिए उसका सी कॉल स्टैक गहराई में भिन्न होता जा रहा है और संभावित रूप से ढेर में वस्तुओं को ओवरराइट कर सकता है। गतिशील स्मृति आवंटन संभव है, लेकिन स्मृति के ऐसे छोटे पूल में सुरक्षित नहीं है। स्टेटिक मेमोरी आवंटन को प्रबंधित करना आसान होगा और एक उचित प्रोग्राम चलाने की संभावना अधिक होगी। – dwhall

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