2012-04-10 19 views
6

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

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

असल में मैं क्या जरूरत है जावा वर्ग वस्तु की तरह कुछ है: डी

पहली बात मैंने कोशिश की एक void* था, लेकिन जाहिरा तौर पर आप B* someB = dynamic_cast<B*>(theVoidPointer) ऐसा नहीं कर सकते, इसलिए कोई किस्मत वहाँ।

मेरा दूसरा विचार boost::any का उपयोग करना था। हालांकि, बूस्ट :: किसी भी का उपयोग करने की आवश्यकता यह है कि मान को प्रतिलिपि बनाने योग्य प्रतिलिपि बनाना चाहिए, जो मेरे डेटा का मामला नहीं है।

इसे काम करने के लिए कोई विचार?

धन्यवाद

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

+2

क्या आप वाकई 'dynamic_cast'' की आवश्यकता है, और 'reinterpret_cast' का उपयोग नहीं कर सकते? –

+1

टेम्पलेट्स का उपयोग करने के बारे में कैसे? –

+0

ऐसा लगता है कि आपके अधिकांश विकल्पों का वर्णन यहां दिया गया है: http://stackoverflow.com/questions/913505/casting-void-pointers-depending-on-data-c – briantyler

उत्तर

1

ठीक है, एक सरल बढ़ावा का उपयोग कर :: किसी भी आपके डेटाटाइप्स की ओर इशारा धारण करने के लिए दृष्टिकोण है। हालांकि, सावधान रहें कि कोई भी ओवरहेड कोड थोड़ा कम प्रदर्शन करता है (ज्यादातर मामलों में उपेक्षित) .. बूस्ट :: भावना :: hold_any का उपयोग करने पर विचार करें, या शून्य * यदि आपको टाइप सुरक्षा की आवश्यकता नहीं है।

class Handler { 
public: 
    void handle(boost::any value) { 
     do_handle(value); 
    } 
private: 
    virtual void do_handle(boost::any& value) = 0; 
}; 

template<class T> 
class HandlerBase : public Handler { 
private: 
    void do_handle(boost::any& value) { 
     // here you should check if value holds type T*... 
     handle_type(*(boost::any_cast<T*>(value))); 
    } 

    void handle_type(const T& value) = 0; 
}; 

class StringHandler : HandlerBase<std::string> { 
private: 
    void handle_type(const std::string& value) { 
     // do stuff 
    } 
}; 

अब आप हैंडलर वर्गों के बहुत सारे लिख सकते हैं, HandlerBase से पाने, यह सोचते हैं कि संभाला प्रकार एक आम आधार वर्ग है बिना।

+0

यह वह समाधान है जिसका उपयोग मैंने टेम्पलेट हैंडलरबेस को छोड़कर किया था। मैंने उसे छोड़ दिया। मैंने बस विशिष्ट हैंडलर को जिस प्रकार की जरूरत है उसे डालने दिया। जैसे ही मेरे पास एक ही डेटा प्रकार के लिए एकाधिक हैंडलर हैं, मैं टेम्पलेट बेस को बीच में रखूंगा। धन्यवाद! –

-1

आप

B* someB = static_cast<B*>(theVoidPointer); 
+2

'static_cast' कृपया। –

+0

@ आर। मार्टिन्होफर्नैंड्स और बर्टआर क्या आप पुन: व्याख्या, स्थिर और गतिशील के बीच अंतरों पर eloborate कृपया कर सकते हैं? मैंने सोचा कि पुनरावृत्ति और स्थैतिक कुछ खतरे थे। –

+0

@ डब्ल्यू। गोमेन इस पिछले प्रश्न को देखें: http://stackoverflow.com/a/332086/46642 –

0

आप DataObject या कुछ और कहा जाता है एक आधार वर्ग की आवश्यकता कर सकते हैं। आपके सभी डेटा प्रकार, (स्ट्रिंग, संख्या, whatnot) DataObject के उप वर्ग हैं। आप इस तरह हैंडल परिभाषित करते हैं:

void Handle(DataObject *dataObject); 

यह वही करने का एक सुरक्षित तरीका है जो आप चाहते हैं। इसे और भी बेहतर बनाने के लिए, डेटाऑब्जेक्ट यह भी जान सकता है कि इसमें किस प्रकार का डेटा है। फिर हैंडलर जांच सकते हैं कि उन्हें सही प्रकार का डेटा भेजा गया है।

class BaseHandlerData { 
    ... 
}; 

फिर अपने विशिष्ट डेटा कक्षाएं, जो अपने संचालकों द्वारा की उम्मीद कर रहे निकाले जाते हैं:

+0

यह मूल रूप से मैंने जो जोड़ा है मेरे संपादन में यह वास्तव में एक अच्छा समाधान की तरह लगता है, लेकिन मैं एक और सामान्य दृष्टिकोण की तलाश में था। यदि अन्य समाधान काम नहीं करते हैं तो भी मैं इसे विकल्पों की सूची में रखता हूं। –

1

आप उदाहरण के लिए एक आधार वर्ग को परिभाषित कर सकते

class StringData: public BaseHandlerData { 
    ... 
}; 

class SomeData: public BaseHandlerData { 
    ... 
}; 

तो फिर तुम एक BaseHandlerData पारित करने के लिए सक्षम होना चाहिए * हैंडल विधि के लिए तर्क, और कुछ का उपयोग करें:

void handle(BaseHandlerData *data) { 
    StringData* stringData = dynamic_cast<StringData*>(...); 
    // handle your string data here ... 
} 

सुरक्षित अपने अपेक्षित डेटा प्रकार के लिए ly cast।

गेराल्ड

+0

यह विस्तार से है जो मैंने अपने संपादन में संक्षेप में कहा था। वास्तव में एक अच्छा समाधान है, लेकिन मैं इसके लिए अतिरिक्त कक्षा नहीं लिखता हूं। मेरे पास यह मूल उपयोगिता (जैसे बूस्ट :: किसी भी) के रूप में है। –

1

एक और विकल्प, C दुनिया की ओर अधिक हो रहा है, union प्रकार (http://en.wikipedia.org/wiki/Union_(computer_science)#C.2FC.2B.2B) होगा। यह आपको केवल प्रकार से निर्दिष्ट प्रकारों को पारित करने की अनुमति देगा, लेकिन आपके द्वारा वर्णित व्यवहार का प्रकार है।