6

आम तौर पर, अगर मैं एक Foo, या एक Bar है, मैं की तरह कुछ करना होगा:क्या एक सामान्य विधि या कक्षा बनाना संभव है जिसे कोई भी किसी भी वर्ग के "नए" उदाहरण बनाने के लिए उपयोग कर सकता है?

Foo* foo = new Foo(); 

Bar* bar = new Bar(2,3,5); 

वहाँ टेम्पलेट्स या मैक्रो का उपयोग कर एक रास्ता है, कि मैं एक समारोह का निर्माण कर सकते हैं, जैसे कि मैं की तरह कुछ कर सकते हैं :

Foo* foo = MyAwesomeFunc(Foo); 
Bar* bar = MyAwesomeFunc(Bar,2,3,5); 

MyAwesomeFunc की वास्तविक विधि हस्ताक्षर मेरे लिए महत्वपूर्ण नहीं है।

Foo और Bar किसी भी संभव तरीके से संबंधित की जरूरत नहीं सकता है, और पूरी तरह से अलग कंस्ट्रक्टर्स हो सकता है। इसके अतिरिक्त, मैं भविष्य में MyAwesomeFunc

कोड को वास्तव में संशोधित किए बिना भविष्य में किसी भी वर्ग का समर्थन करना चाहूंगा? क्या यह संभव है? एक आसान तरीका दोनों Foo और कुछ प्रकार से Bar इनहेरिट, कहते हैं कि Baz, और अतिभारित तरीकों वापसी एक Baz, जो आप Foo या Bar वापस करने के लिए डाली है करने के लिए किया जाएगा ...

Baz* MyAwesomeFunc(){ 
    return new Foo(); 
} 

Baz* MyAwesomeFunc(int a,int b,int c){ 
    return new Bar(a,b,c); 
} 

लेकिन यहाँ समस्या है आप लिखने के लिए होगा:

  1. प्रत्येक वर्ग के लिए एक विधि समर्थित
  2. और निर्माता हस्ताक्षर के प्रत्येक प्रकार के लिए।

लक्ष्य, एक एकल वर्ग, विधि, या मैक्रो, जहां हम कॉल एक समारोह (और यह किसी भी तर्क से पारित), लेकिन कॉल कर सकते हैं वस्तु में पारित की सही निर्माता लिखने के लिए है। क्या यह संभव है ?

इस सवाल का उद्देश्य बस अगर यह सी में इस तरह कुछ करने के लिए संभव है ++ जा सकता है। कृपया साझा पॉइंटर्स, अद्वितीय पॉइंटर्स, नए का उपयोग करने के नुकसान को न लाएं, क्योंकि यह विषय बंद है।

संपादित करें: मैं सी ++ 11 के बाद से केवल एसटीएल

+1

देखें 'बूस्ट :: फैक्टरी' – Ari0nhh

+0

@Ar i0nhh धन्यवाद एर - बूस्ट का उपयोग किये बिना आसानी से ऐसा करने का कोई तरीका? –

+3

प्री सी ++ 11, "परफेक्ट फॉरवर्डिंग" और "वैराडिक टेम्पलेट्स" मौजूद नहीं थे। 'बूस्ट' ने समुदाय को बेवकूफ शक्तिशाली कोड बनाने के लिए उपकरणों के साथ आपूर्ति की और 'बूस्ट :: फैक्ट्री' डिफैक्टो फैक्ट्री थी जिसे पूर्ण अग्रेषण और विविध टेम्पलेट्स द्वारा पार किया गया है। – Gambit

उत्तर

8

उपयोग करें, और बूस्ट जैसी चीजों के प्रयोग से बचें .... आप variadic template और perfect forward साथ यह कर सकते हैं करना चाहते हैं। जैसे एक टेम्पलेट फ़ंक्शन लिखें, जो ऑब्जेक्ट के कन्स्ट्रक्टर को टेम्पलेट पैरामीटर द्वारा निर्दिष्ट प्रकार के साथ अपने पैरामीटर को आगे बढ़ाता है।वैकल्पिक रूप से

#include <type_traits> 
#include <utility> 

template<typename T, typename... Args> 
T* createNew(Args&&... args) 
{ 
    static_assert(std::is_constructible<T, Args...>::value, "T is not constructible with these arguments"); 
    return new T(std::forward<Args>(args)...); 
} 

, आप सी ++ 11 के बाहर की जाँच कर सकते हैं:

template <typename T, typename... Ts> 
T* MyAwesomeFunc(Ts&&... params){ 
    return new T(std::forward<Ts>(params)...); 
} 

तब के रूप में

Foo* foo = MyAwesomeFunc<Foo>(); 
Bar* bar = MyAwesomeFunc<Bar>(2,3,5); 
+1

यदि आप बार बनाने की कोशिश करते हैं, तो सभी आवश्यक तर्कों के बिना क्या होता है? –

+1

आप 'type_traits' से' std :: is_constructible' का उपयोग कर सकते हैं। मेरा जवाब देखें – Gambit

+5

@ जॉन, कंपाइलर त्रुटि। यह बाहर से बिल्कुल सही नहीं लगेगा, लेकिन इसे ठीक करने के तरीके हैं (अवधारणाएं, और इसके अनुकरण)। – chris

8

इसका इस्तेमाल हाँ आप टेम्पलेट का उपयोग और सी ++ 11 के "परफेक्ट अग्रेषण" कर सकते हैं std::make_unique और "स्मार्ट प्वाइंटर्स" What is a smart pointer and when should I use one?

+0

यदि कोई कंपाइलर त्रुटि होगी, तो std :: is_constructible का उपयोग क्यों करें? –

+4

क्योंकि आप अपना संदेश सेट कर सकते हैं और यह भयानक कंपाइलर त्रुटियों में खो जाएगा नहीं। – Gambit

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

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