2009-05-31 16 views
9

वहाँ वैसे भी इस तरह कुछ करने के लिए है के आधार पर रिटर्निंग?अलग डेटा प्रकार डेटा (C++)

(correct pointer datatype) returnPointer(void* ptr, int depth) 
{ 

    if(depth == 8) 
     return (uint8*)ptr; 
    else if (depth == 16) 
     return (uint16*)ptr; 
    else 
     return (uint32*)ptr; 
} 

धन्यवाद

+0

कैसे आप इस का उपयोग करने की उम्मीद करते हैं? संभावना है कि आपका डिज़ाइन सर्वश्रेष्ठ ओओपी प्रथाओं का पालन नहीं करता है। – outis

+0

एडोब फोटोशॉप एसडीके मैं जो उपयोग कर रहा हूं, और वे शून्य * – Joel

+2

का उपयोग करते हैं, क्या आप फ़ोटोशॉप एसडीके फ़ंक्शन को कॉल सहित एक उपयोग उदाहरण दे सकते हैं? – outis

उत्तर

9

नंबर एक सी ++ समारोह की वापसी प्रकार केवल स्पष्ट टेम्पलेट पैरामीटर या प्रकार अपने तर्कों का के आधार पर भिन्न हो सकते हैं। यह अपने तर्कों के मूल्य के आधार पर भिन्न नहीं हो सकता है।

हालांकि, अगर आप एक प्रकार कई अन्य प्रकार का मिलन है कि बनाने के लिए विभिन्न तकनीकों का उपयोग कर सकते हैं। दुर्भाग्यवश यह आपकी मदद नहीं करेगा, क्योंकि ऐसी एक तकनीक शून्य है * और मूल प्रकार पर वापस आना दर्द होगा।

हालांकि, अगर आप बाहर के अंदर समस्या मोड़ तुम क्या चाहते प्राप्त कर सकते हैं द्वारा। मुझे लगता है कि आप उदाहरण के लिए, आप कुछ कोड की तरह के रूप में तैनात का उपयोग करना चाहते हैं: सी ++ संकलन समय पर p_pixels के प्रकार के लिए ज़रूरी है

void bitmap_operation(void *data, int depth, int width, int height) { 
    some_magical_type p_pixels = returnPointer(data, depth); 
    for (int x = 0; x < width; x++) 
    for (int y = 0; y < width; y++) 
     p_pixels[y*width+x] = some_operation(p_pixels[y*width+x]); 
} 

वजह से, यह काम नहीं करेगा के रूप में है।

template<typename PixelType> 
void bitmap_operation_impl(void *data, int width, int height) { 
    PixelType *p_pixels = (PixelType *)data; 
    for (int x = 0; x < width; x++) 
    for (int y = 0; y < width; y++) 
     p_pixels[y*width+x] = some_operation(p_pixels[y*width+x]); 
} 

void bitmap_operation(void *data, int depth, int width, int height) { 
    if (depth == 8) 
    bitmap_operation_impl<uint8_t>(data, width, height); 
    else if (depth == 16) 
    bitmap_operation_impl<uint16_t>(data, width, height); 
    else if (depth == 32) 
    bitmap_operation_impl<uint32_t>(data, width, height); 
    else assert(!"Impossible depth!"); 
} 

अब संकलक आपके लिए अपने आप bitmap_operation_impl के लिए तीन कार्यान्वयन उत्पन्न होगा: लेकिन हम क्या कर सकते हैं अपने आप में bitmap_operation कर एक टेम्पलेट हो, तो एक स्विच गहराई के आधार पर के साथ लपेट है।

+1

सी # में, आप एक ऑब्जेक्ट प्रकार वापस कर सकते हैं, और इसे अपनी वांछित वस्तु में डाल सकते हैं (बशर्ते आप इस प्रकार को जानते हों)। या आप जेनेरिक का उपयोग कर सकते हैं। क्या आप सी ++ में कुछ ऐसा कर सकते हैं? –

+3

निकटतम सी ++ के पास ऑब्जेक्ट प्रकार होना शून्य है *। बूस्ट का वैरिएंट प्रकार भी है। – bdonlan

+0

मुझे लगता है कि मैं भी बढ़ावा संस्करण का उपयोग करेंगे। –

7

यदि आप सामान्य पैरामीटर के बजाय टेम्पलेट तर्क का उपयोग कर सकते हैं, तो आप एक टेम्पलेटेड फ़ंक्शन बना सकते हैं जो प्रत्येक depth मान के लिए सही प्रकार देता है। सबसे पहले depth के अनुसार सही प्रकार की कुछ परिभाषा की आवश्यकता है। आप अलग अलग सा आकार के लिए विशेषज्ञता के साथ एक टेम्पलेट को परिभाषित कर सकते हैं:

// template declaration 
template<int depth> 
struct uint_tmpl; 

// specializations for certain types 
template<> struct uint_tmpl<8> { typedef uint8_t type; }; 
template<> struct uint_tmpl<16> { typedef uint16_t type; }; 
template<> struct uint_tmpl<32> { typedef uint32_t type; }; 

इस परिभाषा एक टेम्प्लेटेड समारोह है कि हर बिट मूल्य के लिए सही प्रकार रिटर्न घोषित करने के लिए इस्तेमाल किया जा सकता:

// generic declaration 
template<int depth> 
typename uint_tmpl<depth>::type* returnPointer(void* ptr); 

// specializations for different depths 
template<> uint8_t* returnPointer<8>(void* ptr) { return (uint8_t*)ptr; } 
template<> uint16_t* returnPointer<16>(void* ptr) { return (uint16_t*)ptr; } 
template<> uint32_t* returnPointer<32>(void* ptr) { return (uint32_t*)ptr; } 
+2

यह टेम्पलेट के बिना समाधान पर कोई लाभ नहीं देता है जैसे returnPointer8(), returnPointer16() और returnPointer32(), क्योंकि टेम्पलेट तर्क निरंतर होना चाहिए (यानी प्रोग्रामर द्वारा ज्ञात) वैसे भी। – Jem

+1

कि टेम्पलेट तर्कों को संकलन समय पर जाना जाना चाहिए टेम्पलेट्स की एक सामान्य संपत्ति है। फिर भी यह अलग-अलग नामित कार्यों की तुलना में अधिक लचीला है, उदाहरण के लिए आप टेम्पलेट ptradd (शून्य * पीआरटी, इंट वैल) {* वापसी सूचक (पीआरटी) + = वैल जैसे कुछ परिभाषित कर सकते हैं; }। यह सभी गहराई के लिए काम करता है। अलग-अलग नामित वापसी सूचक कार्यों के साथ आपको पीआरटीएड के कई अलग-अलग प्रकारों की घोषणा करने की आवश्यकता होगी। टेम्पलेट संस्करण के लिए एक ptradd फ़ंक्शन पर्याप्त है। – sth

1

आप कर सकते हैं ढेर पर कुछ स्मृति आवंटित करें, और एक शून्य * वापस लौटाएं जिसे आपने आवंटित किए गए प्रकार पर डाला था। यह काम करने का एक खतरनाक और असुरक्षित तरीका है और एक पुरानी सी चाल है।

आप एक यूनियन वापस कर सकते हैं जिसमें सभी वैध डेटाटाइप (और चयन सूचक) शामिल हैं।

आप टेम्पलेट्स का उपयोग कर सकते हैं, जो कि इस तरह की चीज़ के लिए अनुशंसित सी ++ तरीका है।

आप अधिभारित कार्यों का एक सेट प्रदान कर सकते हैं जो संदर्भ के रूप में पैरामीटर (प्रत्येक प्रकार का) लेते हैं - संकलक तय करेगा कि डेटाटाइप के आधार पर कौन सा फ़ंक्शन कॉल करना है। मैं अक्सर इस तरह से पसंद करता हूं क्योंकि मुझे लगता है कि यह सबसे सरल है।

0

नहीं; आप इसे C++ में नहीं कर सकते हैं। सही जवाब void * वापस करना है।

कॉल के विपरीत दिशा से इसके बारे में सोचो - और उस पर देखने के संकलक बिंदु से:

वापसी मान सही ढंग से प्रयोग किया जाता है (जैसे एक करने के लिए सौंपा कैसे संकलक को सत्यापित करने में सक्षम होगा उचित प्रकार के चर, उदाहरण के लिए), यदि यह संभवतः नहीं पता कि तीन रिटर्न प्रकारों में से कौन सा वापस किया जाएगा?

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

यदि आपकी गहराई के तर्क संकलन समय पर ज्ञात हैं, तो आप वैकल्पिक रूप से @sth जैसे टेम्पलेट्स का एक सेट उपयोग कर सकते हैं, या अलग-अलग स्वतंत्र कार्यों के सेट का उपयोग कर सकते हैं, या संबंधित कार्यों के एक सेट का उपयोग कर सकते हैं जो साझा कार्यान्वयन फ़ंक्शन को कॉल करते हैं और फिर उचित प्रकार पर वापसी कास्ट करें। आपने जो चुना है वह ज्यादातर सौंदर्य निर्णय है।

यदि depth का मान रन-टाइम तक नहीं पता है, तो आपको शायद void * वापस जाना चाहिए।

अब, मुझे लगता है कि आपका वास्तविक कार्यान्वयन वास्तव में आपके नमूना कोड के अलावा पॉइंटर का उत्पादन करने के लिए कुछ करता है। आपका नमूना कोड वास्तविक कार्य नहीं है; यह cast करता है जो डुप्लिकेट करने की कोशिश कर रहा है। एक cast फ़ंक्शन कॉल नहीं है; यह एक विशिष्ट प्रकार (बिल्कुल 'कैसे', एक और पोस्ट के लिए एक लंबी कहानी है) में "ऑपरेशन" करने की कोशिश करने के लिए एक संकलक निर्देश है। यह एक सी ++ भाषा ऑपरेशन नहीं है, लेकिन एक कंपाइलर ऑपरेशन है। आप सी ++ में खुद को फिर से लिख नहीं सकते हैं।

0

आप यह कर सकते हैं:

अगर (गहराई == 8) (uint8 *) returnPointer (शून्य * ptr, पूर्णांक गहराई) {// आदि

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