2012-01-04 8 views
5

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

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

class ItemBase { 
    // common methods 
}; 

class ItemInt : public ItemBase 
{ 
    private: 
    int dat; 
    public: 
    int get() { return dat; } 
}; 

class ItemDouble : public ItemBase 
{ 
    private: 
    double dat; 
    public: 
    double get() { return dat; } 
}; 

class Container { 
public: 
    void post(int postHandle, ItemBase *e);  
    ItemBase* receive(int handle); // Returns the associated Item 
}; 

int main() 
{ 
    ItemInt *ii = new IntItem(5); 
    Container c; 
    c.post(1, ii); 

    ItemInt *jj = c.receive(1); 
    int val = jj->get(); // want the value 5 out of the IntItem 
} 
+1

Boost.any का प्रयास करें, जो कुछ बहुत समान करता है। –

+0

यह भी ध्यान रखें कि पोस्ट किए गए कोड में प्रत्येक ऑब्जेक्ट की 'get' की समस्या का एक अलग रिटर्न प्रकार होगा। यदि आप उन्हें एक ही प्रकार नहीं बना सकते हैं, तो आपको स्ट्रिंगस्ट्रीम या कुछ वापस करना होगा। –

+0

हां मैं सहमत हूं, लेकिन get() फ़ंक्शन वर्चुअल फ़ंक्शन नहीं है। यह "अलग कार्यक्षमता" है कि प्रत्येक व्युत्पन्न वर्ग "जोड़ता है"। अन्य सामान्य कार्यक्षमता है जो विरासत को "जरूरी" –

उत्तर

5

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

+0

मैं मानता हूं कि हम एक टेम्पलेट आइटम बना सकते हैं और() वापस टी प्राप्त कर सकते हैं। लेकिन पोस्ट करने के लिए दूसरा तर्क किस प्रकार होगा()? मैं इसे किसी भी टेम्पलेट पैरामीटर के साथ आइटम स्वीकार करना चाहता हूं, टी –

+0

@innocent_bystander: आम तौर पर मैं 'कंटेनर :: पोस्ट' और 'कंटेनर :: दोनों टेम्पलेट्स' प्राप्त करता हूं, और 'आइटमबेस' altogeather को छोड़ देता हूं। –

0

आपकी कंटेनर कक्षा संदिग्ध रूप से std :: map की तरह दिखती है। ऐसा लगता है कि आपकी मदरबेस श्रेणी "ऑब्जेक्ट", सार्वभौमिक बेस क्लास के लिए सिर्फ एक अलग नाम है, जो मुझे लगता है कि शून्य से (या बेहतर) शून्य से बहुत अलग नहीं है। मैं एक ही कंटेनर में विभिन्न प्रकार की वस्तुओं को रखने की कोशिश करने से बचूंगा। यदि आपका डिज़ाइन ऐसा करने के लिए कॉल करता है, तो मैं आपके डिज़ाइन पर पुनर्विचार करूंगा।

0

कैसे?

template<typename T> 
class Item 
{ 
    private: 
    T dat; 
    public: 
    T get() { return dat; } 
}; 

class Container { 
public: 
    template<typename T> 
    void post(int postHandle, Item<T> *e);  

    template<typename T> 
    Item<T>* receive(int handle); // Returns the associated Item 
}; 

int main() 
{ 
    Item<int> *ii = new Item<int>(5); 
    Container c; 
    c.post(1, ii); 

    Item<int> *jj = c.receive<int>(1); 
    int val = jj->get(); // want the value 5 out of the IntItem 
} 
0

एक शुद्ध टेम्पलेट दृष्टिकोण काम नहीं करता है क्योंकि आप स्पष्ट रूप से अपने कंटेनर में मिश्रित प्रकार चाहते हैं। आप बूस्ट के any जैसे कुछ के साथ काम कर सकते हैं हालांकि मुझे लगता है कि आपको वास्तविक को पुनर्स्थापित करने की आवश्यकता है।

class Base { 
public: 
    virtual ~Base() {} 
    virtual void post() = 0; 
}; 

template <typename T> 
class Item: public Base { 
public: 
    Item(T const& value): value_(value) {} 
    void post() { std::cout << "posting " << this->value_ << "\n"; } 
private: 
    T value_; 
}; 

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

template <typename T> 
std::unique_ptr<Base> make_item(T const& value) { 
    return std::unique_ptr<Base>(new Item<T>(value)); 
} 

एक std::unique_ptr<Base> सुनिश्चित करें कि आवंटित वस्तु जारी किया गया है बनाने के लिए (यदि आप सी ++ 2011 का उपयोग नहीं करते आप std::auto_ptr<T> बजाय प्रयोग किया जा सकता है) दिया जाता है। इस प्रकार को आसानी से अन्य सूचक प्रकारों में परिवर्तित किया जा सकता है, उदा। std::shared_ptr<Base> पर जो एक कंटेनर में डालने के लिए बेहतर अनुकूल है।