2009-10-11 18 views
5

क्लास कैलेंडर पर विचार करें जो डेट ऑब्जेक्ट्स का एक गुच्छा स्टोर करता है। कैलेंडर को किसी भी प्रकार की ऑब्जेक्ट्स का संग्रह रखने के लिए डिज़ाइन किया गया है जो दिनांक से प्राप्त होता है। मैं सबसे अच्छा तरीका करने के लिए सोचा था कि यहसी ++: पॉलिमॉर्फिक क्लास टेम्पलेट

template<typename D> class Calendar{ 
    ... 
} 

के रूप में एक वर्ग टेम्पलेट इस तरह है लेकिन यह मुझे लगा कि डी अब वास्तव में किसी भी वर्ग हो सकता है। मेरा प्रश्न अब है, मैं कैसे सुनिश्चित कर सकता हूं कि डी दिनांक वस्तु का उप-वर्ग है?

मुझे पता है कि यह जावा कैसे करें, लेकिन मैं अभी भी सी ++ वाक्यविन्यास से अपरिचित हूं। समस्या बहुत समान है कि कुछ संग्रह केवल टेम्पलेट चर ले सकते हैं जो तुलनात्मक लागू करते हैं। हैडर तो

public class Calendar<D extends Date>{ 
    ... 
} 

-------------------- संपादित करें कुछ ऐसा दिखाई देगा: -------------- ----------------------------

टेम्पलेट तर्क परिभाषित करता है कि कैलेंडर किस वास्तविक दिन को संदर्भित करता है। विभिन्न दिनांक प्रकार उसी प्रारूप को विभिन्न प्रारूपों में संदर्भित करते हैं। उदाहरण के लिए, यदि मैं Calendar<Gregorian> बना देता हूं तो यह अन्य Date प्रारूप में दिनांक लेने में सक्षम होगा, जूलियन कैलेंडर या किसी अन्य दिनांक प्रारूप का कहना है और उन्हें ग्रेगोरियन प्रारूप में प्रस्तुत करें। यह विभिन्न दिनांक प्रारूपों में कैलेंडर के बीच रूपांतरण के लिए सक्षम बनाता है। इसलिए, यदि मेरे पास Calendar<Gregorian> है तो मैं इसे आसानी से Calendar<Julian> में परिवर्तित कर सकता हूं। उसके बाद निम्न संभव है:

Calendar<Gregorian> cal; 
std::cout << "These events are entered as dates in 
    the Gregorian calendar" << std::endl; 
cal.add_event("Christmas", 12, 25); 
cal.add_event("Gregorian new year", 1, 1); 
std::cout << cal << std::endl; 
std::cout << "----" << std::endl; 
std::cout << "And printed out as Julian dates" << std::endl; 
Calendar<Julian>(cal); 
std::cout << cal<< std::endl; 

और आउटपुट:

These events are entered as dates in the Gregorian calendar 
2009-12-25 Christmas 
2010-01-01 Gregorian new year 
---- 
And printed out as Julian dates 
2009-12-13 Christmas 
2009-12-19 Gregorian new year 

------------- न्यू संपादित करें: ----------- -----------

अंतिम संपादन अब और अधिक समझ में आता है। स्वरूपण के साथ मुझे थोड़ा असहमति थी।

सभी उत्तरों के लिए धन्यवाद।

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

+2

* तारीख * के उप-वर्ग होने की आवश्यकता क्यों है? जब तक यह एक तिथि के रूप में व्यवहार करता है (सही सदस्यों का खुलासा करता है), इसे तिथि के रूप में इलाज करने में क्या गलत है? – jalf

उत्तर

9

मुझे पता है कि यह जावा कैसे करें, लेकिन मैं अभी भी सी ++ वाक्यविन्यास से अपरिचित हूं। समस्या बहुत समान है कि कुछ संग्रह केवल टेम्पलेट चर ले सकते हैं जो तुलनात्मक लागू करते हैं। हैडर तो

public class Calendar<D extends Date>{ 
    ... 
} 

यह सच है कुछ ऐसा दिखाई देगा, यह एक ही समस्या है, और सी ++ में, यह आमतौर पर यह अनदेखी करके हल किया जाता है। हमें यह लागू करने की आवश्यकता क्यों है कि ऑब्जेक्ट IComparable लागू करना चाहिए? जावा में, यह अपने एनीमिक प्रकार प्रणाली के कारण जरूरी है। इस बाधा के बिना, हम वस्तुओं की तुलना करने में असमर्थ होंगे।

सी ++ में, नियम अलग हैं। कंटेनर बस को उनके द्वारा संग्रहीत वस्तुओं की तुलना करने के लिए प्रयास करें, और यदि प्रकार इसका समर्थन नहीं करता है, तो आपको संकलन त्रुटि मिलती है। कोई इंटरफेस या विरासत की आवश्यकता नहीं है।

और आप आमतौर पर अपने Calendar कक्षा में ऐसा ही करेंगे। बस लागू नहीं करें "उप-वर्ग Date बाधा होना चाहिए।

इसके बजाय, उन सदस्यों को निर्दिष्ट करें जिन्हें प्रकार का खुलासा करना चाहिए, और क्या, यदि कोई हो, तो उनसे अर्थशास्त्र की अपेक्षा की जानी चाहिए।

d0.getDay(); 
d0.getTime(); 
Time t = d0 - d1; 

तो उन है कि समर्थन किया जाना चाहिए संचालन कर रहे हैं:

उदाहरण के लिए, यदि आपके कैलेंडर निम्न कार्रवाई करने के लिए, तारीख वस्तुओं के लिए d0 और d1 प्रयास करता है। कोई भी वर्ग जो इन परिचालनों का समर्थन करता है एक मान्य दिनांक वर्ग है, भले ही यह कुछ भी उपclass न हो।

+0

आईएमओ अब तक का सबसे अच्छा जवाब है। काश है कि मेरा जवाब बस इतना कहता कि बतख टाइपिंग ठीक है। स्थिर polymorphism का उपयोग करने के लिए +1 – sbi

+1

+1 –

3

मुझे लगता है कि आपकी समस्या टेम्पलेट का उपयोग किए बिना हल करने योग्य है। डी हमेशा दिनांक का व्युत्पन्न वर्ग होता है, तो क्यों न केवल दिनांक वस्तुओं का संग्रह होता है?

+0

दरअसल, मैं ज्यादातर वाक्यविन्यास का उत्सुक हूं, लेकिन कक्षा के कुछ कार्यों (प्रश्न के लिए अप्रासंगिक) के लिए भी आवश्यक है कि मेरे पास एक सटीक प्रकार है। – Nubsis

0

यदि आप केवल डेट ऑब्जेक्ट्स के साथ बातचीत करना चाहते हैं, तो क्यों न केवल सादा बहुरूपता का उपयोग करें और बस दिनांक * -s से निपटें?

यदि आप कैलेंडर में तिथियों का संग्रह करने की योजना बनाते हैं, जिसमें विभिन्न दिनांक उप-वर्गों के उदाहरण हो सकते हैं, तो मुझे संदेह है कि टेम्पलेट काम करने जा रहे हैं और आपके पास पहले स्थान पर आपकी मदद करने के लिए बहुरूपता के अलावा कुछ भी नहीं है।

टेम्पलेट्स के रूप में, यदि किसी दिए गए प्रकार के पास उपयुक्त इंटरफ़ेस है, तो यह कैलेंडर के साथ क्यों काम नहीं करना चाहिए? (खैर, अवधारणाओं को सी ++ 0x के लिए योजनाबद्ध किया गया था, लेकिन गिरा दिया गया, लेकिन उनका मुख्य प्रेरणा स्पष्ट टेम्पलेट से संबंधित त्रुटि संदेशों को अनुमति देने के लिए प्रतीत होता था।)

8

आप जो खोज रहे हैं वह टेम्पलेट तर्कों के लिए अवधारणा जांच है। ये अगले सी ++ मानक के मसौदे का हिस्सा थे, लेकिन कुछ सप्ताह/महीने पहले फिर से बाहर फेंक दिया गया था।

भाषा में अवधारणाओं के बिना, कुछ पुस्तकालय हैं जो ऐसा करने का प्रयास करते हैं, लेकिन मूल भाषा का हिस्सा होने की अवधारणा जांच की इच्छा यह है कि भाषा समर्थन के बिना उन्हें लागू करना कम या ज्यादा असंभव है।

आपके ठोस उदाहरण में यह बहुत कठिन नहीं होना चाहिए, हालांकि। उदाहरण के लिए, आप आधार वर्ग में कुछ विशेष typedef डाल सकता है और जाँच लें कि के लिए:

class date { 
    public: 
    typedef int is_derived_from_date; 
}; 

template<typename D> class Calendar{ 
    typedef typename D::is_derived_from_date blah; 
    ... 
}; 

एक और तरीका होगा is_derived<B,D>::result टेम्पलेट मेटा नेट पर चारों ओर चल कार्यों के किसी भी लेने के लिए और इस के लिए एक स्थिर जांच लागू आपके Calender कक्षा में। Boost दोनों is_derived मेटा फ़ंक्शन और एक स्थिर जोर है।

यह सब कहकर, मुझे आपके डिजाइन पर सवाल उठाना है। सामान्य ओओ polymorphism के साथ क्या गलत है कि आप टेम्पलेट्स संकलन-समय polymorphism का उपयोग करना चाहते हैं?

+1

पुन। अंतिम अनुच्छेद, टेम्पलेट्स संकलन-समय बहुरूपता के साथ क्या गलत है, कि आप साधारण ओओ बहुरूपता का उपयोग करना चाहते हैं? मैं सहमत हूं, मिश्रण अजीब है। हमारे पास कौन सी जानकारी है, ऐसा लगता है कि दोनों गतिशील और स्थैतिक बहुरूपता काम कर सकती है। और फिर मैं स्थिर पसंद करेंगे। – jalf

+0

@jalf: मैं भी हो सकता है। लेकिन सवाल से ऐसा लगता है कि मार्को पहले ही ओओ पॉलिमॉर्फिज्म को अच्छी तरह से जानता है, जबकि आईएमई में बहुत से समय लगता है कि उन्नत टेम्पलेट सामान और स्थैतिक बहुरूपता क्या है। तो ओओ को जानने वाले सी ++ शुरुआती लोगों के लिए, मैं तब तक चिपकने का सुझाव दूंगा जब तक वे इसे करने के सी ++ तरीके से अधिक परिचित महसूस न करें। – sbi

+0

सच। या तो दृष्टिकोण मान्य है। टेम्पलेट रूट अधिक मूर्खतापूर्ण सी ++ होगा, मुझे लगता है, लेकिन ओओ शुरुआती और गैर-सी ++ प्रोग्रामर से अधिक परिचित है। यह सिर्फ उन दोनों का मिश्रण है जो समस्याग्रस्त हो जाते हैं। – jalf

1

टेम्पलेट्स आमतौर पर विरासत/बहुरूपता प्रतिबंधों की आवश्यकता नहीं होती है। एक टेम्पलेट को के साथ काम करने के लिए डिज़ाइन किया गया है प्रकार जो कि बेस प्रकारों के बावजूद दी गई आवश्यकताओं को पूरा करता है।

template <typename T> 
T clone(const T& cloneable) { 
    return cloneable.create_clone(); 
} 

इस कोड को किसी भी प्रकार की है कि के लिए काम करेंगे एक create_clone() कार्रवाई का समर्थन करता है, कोई ICloneable -interface प्रयोग किया जाता है!

आपके मामले में, यह कोड किसी भी प्रकार की अनुमति देगा जो उपयोग की जाने वाली तारीख की तरह व्यवहार करता है।

यदि आप बेस क्लास पॉलिमॉर्फिज्म चाहते हैं, तो बस टेम्पलेट्स को छोड़ दें और Date* का उपयोग करें।

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

2

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

संकल्पना जांच C++ 0x में हटा दी गई थी, लेकिन आप इसे Boost.ConceptCheck (बूस्ट मुख्य साइट here) में पा सकते हैं।

तुम सच में Date से कि D inherits लागू करने के लिए, हालांकि चाहते हैं, आप Boost.StaticAssert संयोजन में Boost.TypeTraits साथ Date से अगर D inherits जाँच करने के लिए उपयोग कर सकते हैं।

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