2008-10-12 3 views
9

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

वास्तविक संसाधन से निपटने के बिना कोई एक आरएआईआई कक्षा का नकल कैसे करता है?

उत्तर

12

आप इसके बजाय एक इंटरफ़ेस बनाते हैं जो इस प्रकार का वर्णन करता है, और वास्तविक वर्ग और नकली वर्ग दोनों से इसका उत्तराधिकारी है। तो अगर आप था:

class RAIIClass { 
public: 
    RAIIClass(Foo* f); 
    ~RAIIClass(); 
    bool DoOperation(); 

private: 
    ... 
}; 

आप की तरह एक अंतरफलक बनाना होगा:

class MockableInterface { 
public: 
    MockableInterface(Foo* f); 
    virtual ~MockableInterface(); 
    virtual bool DoOperation() = 0; 
}; 

और वहां से चले जाते हैं।

+0

बिल्कुल कहां जाना है? आरएआईआई कक्षाओं का उपयोग आमतौर पर मूल्य द्वारा किया जाता है, ढेर पर आवंटित नहीं किया जाता है। वे ज्यादातर निर्धारक जीवनकाल के लिए ढेर पर ढेर वस्तुओं को संभालने के लिए उपयोग किया जाता है। [उदाहरण] (https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization) – zahir

6

सबसे पहले, यह अनिवार्य रूप से एक अनुचित चीज़ नहीं है कि आपके वर्ग उनके उपयोग के लिए अच्छी तरह से डिजाइन किए जा सकें, लेकिन परीक्षण के लिए खराब डिजाइन किए गए हैं। परीक्षण करने के लिए सबकुछ आसान नहीं है।

संभवतः आप किसी अन्य फ़ंक्शन या क्लास का उपयोग करना चाहते हैं जो उस वर्ग का उपयोग करता है जिसे आप नकल करना चाहते हैं (अन्यथा समाधान छोटा है)। आइए पूर्व "उपयोगकर्ता" और बाद वाले "मॉक" को कॉल करें। यहाँ कुछ संभावनाएं हैं:

  1. बदलें उपयोगकर्ता मज़ाक उड़ाया का एक सार संस्करण का उपयोग करने (आप क्या अमूर्त की तरह उपयोग करने के लिए चुनना होता है: विरासत, कॉलबैक, टेम्पलेट्स, आदि ....)।
  2. अपने परीक्षण कोड के लिए मॉक किए गए एक अलग संस्करण को संकलित करें (उदाहरण के लिए, जब आप अपने परीक्षण संकलित करते हैं तो # RAII कोड को हटाएं)।
  3. मॉक किए गए हैं अपने व्यवहार को बंद करने के लिए एक निर्माता ध्वज स्वीकार करते हैं। मैं व्यक्तिगत रूप से ऐसा करने से बचूंगा।
  4. बस संसाधन आवंटित करने की लागत को चूसो।
  5. परीक्षण छोड़ें।

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

0

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

परीक्षण समय पर, आप एक नकली में स्वैप करते हैं जो कोई धागा नहीं बनाता है, लेकिन केवल उस विधि के लिए आगे बढ़ता है जिसे आप परीक्षण करना चाहते हैं।

class Base{ 
protected: 
    Base* decorated; 
public: 
    virtual void method(void)=0; 
}; 
class Final: public Base{ 
    void method(void) { Thread athread; decorated->method(); } // I expect Final to do something with athread 
}; 
class TestBase: public Base{ 
    void method(void) { decorated->method(); } 
}; 
1

पिंपल मुहावरे आपको भी अनुकूल कर सकता है। अपनी थ्रेड क्लास बनाएं, जिसमें एक ठोस कार्यान्वयन है जो नीचे लाता है। यदि आप दाएं # डिफाईन्स और #ifdefs डालते हैं तो जब आप यूनिट परीक्षण सक्षम करते हैं तो आपका कार्यान्वयन बदल सकता है, जिसका अर्थ यह है कि आप एक वास्तविक कार्यान्वयन और एक मजाकिया व्यक्ति के बीच स्विच कर सकते हैं जो आप पूरा करने की कोशिश कर रहे हैं।