2015-06-06 12 views
8

के लिए कक्षा का विस्तार करने के बराबर है, जावा में, एक ऐसा फ़ंक्शन बनाने के लिए जो एक ऑब्जेक्ट देता है जो पैरामीटर के समान प्रकार है और एक निश्चित वर्ग तक फैलाता है, मैं टाइप करूंगा:सी ++ जावा पैरामीटर/रिटर्न प्रकार

public <T extends MyClass> T foo(T bar) {...} 

क्या कोई सी ++ इसके बराबर है?

दूसरे शब्दों में, मैं एक ऐसा कार्य कैसे करूं जो किसी भी वर्ग को एक निश्चित वर्ग तक फैलाता है, और उसी प्रकार देता है? (यह सार/शुद्ध वर्चुअल कक्षाओं के उद्देश्य के लिए है)।

+0

यह टेम्पलेट्स की प्रकृति है। – AndyG

+0

जावा और सी ++ जेनेरिक एक बहुत अलग लगता है। –

+0

@AndyG एक टेम्पलेट वास्तव में क्या है, और मैं इस परिदृश्य में इसका उपयोग कैसे करूं? – ricky3350

उत्तर

8

हम enable_if यहाँ उपयोग कर सकते हैं अगर आप सी ++ 11 या उसके बाद आप

template<typename T, typename std::enable_if<std::is_base_of<MyClass, T>::value>::type* = nullptr> 
T Foo(T bar) 
{ 
    return T(); 
} 

उदाहरण के लिए के लिए उपलब्ध है:

class MyClass 
{ 
public: 
    int a = 1; 
}; 

class Derived : public MyClass 
{ 
public: 
    int b = 2; 
}; 

class NotDerived 
{ 
public: 
    int b = 3; 
}; 

template<typename T, typename std::enable_if<std::is_base_of<MyClass, T>::value>::type* = nullptr> 
T Foo(T bar) 
{ 
    return T(); 
} 

int main() 
{ 
    Derived d; 
    NotDerived nd; 
    std::cout << Foo(d).b << std::endl;; // works 
    //std::cout << (Foo(nd)).b << std::endl;; //compiler error 

    return 0; 
} 

Live Demo

+0

# शामिल std :: enable_if और std :: is_base_of के लिए जोड़ा जाना चाहिए। – user1056903

+0

@ user1056903: '# शामिल 'जो मेरे पास डेमो में है, और संभवतः पसंदीदा है। – AndyG

0

जब से मैं इस पर टिप्पणी नहीं कर सकते हैं स्वीकार्य उत्तर, मैं एक नया उत्तर प्रदान कर रहा हूं जो इस पर बनाता है।

enable_if स्थिति nullptr के बजाय default type template parameter बनकर टेम्पलेट पैरामीटर को सरल बनाया जा सकता है।

template<typename T, typename = std::enable_if<std::is_base_of<MyClass, T>::value>> 
8

तकनीकी रूप से, जैसा कि अन्य उत्तरों दिखाते हैं, संकलन समय पर किसी निश्चित प्रकार के उपप्रकारों को प्रतिबंधित करने के तरीके हैं। हालांकि, ज्यादातर समय, आप केवल

template <typename T> T foo(T bar) {...} 

को बाध्य निर्दिष्ट करने की आवश्यकता के बिना करेंगे।

जावा में, जेनेरिक के लिए सीमाओं की आवश्यकता होती है क्योंकि जेनेरिक क्लास या विधि को इसके किसी भी उपयोग से अलग से संकलित किया जाता है। जेनेरिक कक्षाओं या विधियों को बाइटकोड में एक ही संस्करण में एक बार संकलित किया जाता है, एक ऐसा संस्करण जो कॉलर फेंकने वाले किसी भी तर्क को संभालने में सक्षम होता है जो इसकी घोषणा में सीमाओं को पूरा करता है।

संकलक टाइप की जांच करना चाहिए प्रकार T की, विधि कॉल की तरह, विधि के शरीर में उपयोग करता है, क्षेत्र, तक पहुँचता है आदि, यह जानकर क्या T है बिना ऐसा कराने के लिए आपको बाध्य तो संकलक संतुष्ट किया जा सकता है उदाहरण के लिए एक विधि कॉल मान्य है क्योंकि यह उस प्रकार को परिभाषित करता है जो उस सीमा को पूरा करता है। उदाहरण के लिए, यदि आपके पास विधि के शरीर में bar.baz() अभिव्यक्ति थी, तो संकलक केवल तभी संकलित करेगा जब MyClass (और इसलिए इसके सभी उपप्रकार) विधि .baz() प्रदान करता है; यदि आपने कोई सीमा प्रदान नहीं की है, तो संकलक शिकायत करेगा कि Object (निहित ऊपरी सीमा) में कोई विधि .baz() नहीं है।

सी ++ टेम्पलेट अलग हैं। टेम्पलेटेड क्लास या फ़ंक्शन "तत्काल" (फिर संकलित) होता है जिसके लिए प्रत्येक अलग-अलग प्रकार के तर्क के लिए उपयोग किया जाता है। इसलिए किसी विशेष T के लिए फ़ंक्शन के बॉडी को संकलित करने के समय, कंपाइलर जानता है कि T क्या है, और उस प्रकार के उपयोग को सीधे टाइप करने में सक्षम है।

तो यदि आपके पास समारोह के शरीर में bar.baz() अभिव्यक्ति थी, तो यह ठीक होगा। यदि आपने T के साथ इस फ़ंक्शन का उपयोग MyClass तक बढ़ाया है, तो यह ठीक संकलित होगा, क्योंकि इस प्रकार के .baz() है।यदि आप इस फ़ंक्शन का उपयोग उस प्रकार के साथ करते हैं जिसमें .baz() नहीं है, तो यह उस उपयोग पर संकलन करने में विफल हो जाएगा। यदि आप गलती से फ़ंक्शन का उपयोग ऐसे प्रकार से करते हैं जो MyClass का विस्तार नहीं करता है लेकिन .baz() है जिसका पैरामीटर प्रकार और रिटर्न प्रकार जिस तरह से आप इसका उपयोग कर रहे हैं, उससे मेल खाता है, यह भी संकलित होगा; लेकिन यह एक बुरी बात नहीं है। सी ++ टेम्पलेट्स आमतौर पर टाइप पदानुक्रमों के साथ उपयोग नहीं किए जाते हैं, बल्कि इस प्रकार की आवश्यकता के साथ कि किस प्रकार की आवश्यकता है। तो उदाहरण के लिए, एक सॉर्टिंग एल्गोरिदम की आवश्यकता नहीं होगी कि इसके कंटेनर और/या तत्व प्रकार एक निश्चित प्रकार का विस्तार करें, बल्कि कंटेनर कुछ विशेषताओं (उदाहरण के लिए यादृच्छिक एक्सेस सबस्क्रिप्ट ऑपरेटर) प्रदान करता है, और तत्व प्रकार कुछ विशेषताओं (उदाहरण के लिए) ऑपरेटर से कम)।

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