C ++ और Java में "जेनेरिक" प्रकारों के बीच अंतर क्या हैं?


153

जावा में जेनेरिक है और सी ++ templateएस के साथ एक बहुत मजबूत प्रोग्रामिंग मॉडल प्रदान करता है । तो फिर, C ++ और Java जेनरिक में क्या अंतर है?


जवाबों:


144

उनके बीच एक बड़ा अंतर है। C ++ में आपको सामान्य प्रकार के लिए एक वर्ग या एक इंटरफ़ेस निर्दिष्ट करने की आवश्यकता नहीं है। यही कारण है कि आप सही ढंग से सामान्य कार्यों और कक्षाएं बना सकते हैं, एक शिथिल टाइपिंग के कैवेट के साथ।

template <typename T> T sum(T a, T b) { return a + b; }

ऊपर दी गई विधि एक ही प्रकार की दो वस्तुओं को जोड़ती है, और इसका उपयोग किसी भी प्रकार T के लिए किया जा सकता है जिसमें "+" ऑपरेटर उपलब्ध है।

जावा में आपको एक प्रकार निर्दिष्ट करना होगा यदि आप पास की गई वस्तुओं पर विधियों को कॉल करना चाहते हैं, कुछ इस तरह से:

<T extends Something> T sum(T a, T b) { return a.add ( b ); }

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

Something sum(Something a, Something b) { return a.add ( b ); }

जावा में इतनी सामान्य प्रोग्रामिंग वास्तव में उपयोगी नहीं है, यह केवल नए फ़ॉरेक्स निर्माण के साथ मदद करने के लिए थोड़ी सी सिन्सेटिक चीनी है।

EDIT: उपयोगिता पर ऊपर की राय एक छोटे स्वयं द्वारा लिखी गई थी। जावा के जेनेरिक पाठ्यक्रम की सुरक्षा के साथ मदद करते हैं।


27
वह पूरी तरह से सही है कि यह केवल एक विस्तृत सियाटिक शर्करा है।
अल्फाजो

31
यह विशुद्ध रूप से वाक्यगत चीनी नहीं है। कंपाइलर इस जानकारी का उपयोग चेकिंग प्रकारों के लिए करता है। हालाँकि, जानकारी रनटाइम पर उपलब्ध नहीं है, मैं संकलित उपयोगों को "सिंटैक्टिक शुगर" नहीं कहूंगा। यदि आप इसे कहते हैं कि, ठीक है, तो सी असेंबली के लिए सिंटैक्टिक शुगर है, और यह मशीन कोड के लिए सिंटैक्टिक शुगर है :)
dtech

42
मुझे लगता है कि सिंटैक्टिक चीनी उपयोगी है।
कविता १३'१३ को

5
आप अंतर के एक प्रमुख बिंदु से चूक गए, आप एक जेनेरिक को तत्काल करने के लिए क्या उपयोग कर सकते हैं। C ++ में टेम्पलेट <int N> का उपयोग करना और किसी भी संख्या के लिए एक अलग परिणाम प्राप्त करना संभव है ताकि इसे तुरंत किया जा सके। इसका उपयोग संकलन समय मेटा प्रोगेमिंग के लिए किया जाता है। जैसे उत्तर में: stackoverflow.com/questions/189172/c-templates-turing-complete
stonemetal

2
आपको 'एक प्रकार' निर्दिष्ट करने की आवश्यकता नहीं है, extendsया तो के रूप में super। उत्तर गलत है,
लोरेन का मार्क्विस

124

जावा जेनेरिक C ++ टेम्प्लेट में बड़े पैमाने पर भिन्न होते हैं ।

मूल रूप से C ++ टेम्प्लेट में मूल रूप से एक महिमामंडित प्रीप्रोसेसर / मैक्रो सेट होता है ( नोट: चूंकि कुछ लोग एक सादृश्य को समझने में असमर्थ हैं, मैं यह नहीं कह रहा हूं कि टेम्प्लेट प्रोसेसिंग एक मैक्रो है)। जावा में वे मूल रूप से सिंटैक्टिक शुगर हैं जो वस्तुओं के बॉयलरप्लेट कास्टिंग को कम करते हैं। यहाँ जावा जेनिक्स बनाम सी ++ टेम्पलेट्स के लिए एक बहुत ही अच्छा परिचय है

इस बिंदु पर विस्तार से बताने के लिए: जब आप C ++ टेम्पलेट का उपयोग करते हैं, तो आप मूल रूप से कोड की एक और प्रतिलिपि बना रहे हैं, जैसे कि आपने एक #defineमैक्रो का उपयोग किया हो । यह आपको intटेम्प्लेट परिभाषाओं में पैरामीटर जैसी चीजें करने की अनुमति देता है जो एरे और इस तरह के आकार निर्धारित करते हैं।

जावा ऐसा काम नहीं करता है। जावा में सभी ऑब्जेक्ट्स java.lang.Object से सीमा तक हैं , पूर्व पीढ़ी के, आप इस तरह कोड लिखेंगे:

public class PhoneNumbers {
  private Map phoneNumbers = new HashMap();

  public String getPhoneNumber(String name) {
    return (String)phoneNumbers.get(name);
  }

  ...
}

क्योंकि सभी जावा संग्रह प्रकारों ने ऑब्जेक्ट को उनके आधार प्रकार के रूप में उपयोग किया है ताकि आप उनमें कुछ भी डाल सकें। जावा 5 चारों ओर घूमता है और जेनेरिक जोड़ता है ताकि आप निम्न चीजें कर सकें:

public class PhoneNumbers {
  private Map<String, String> phoneNumbers = new HashMap<String, String>();

  public String getPhoneNumber(String name) {
    return phoneNumbers.get(name);
  }

  ...
}

और यह सभी जावा जेनेरिक हैं: कास्टिंग ऑब्जेक्ट्स के लिए रैपर। ऐसा इसलिए है क्योंकि Java Generics को परिष्कृत नहीं किया गया है। वे प्रकार के क्षरण का उपयोग करते हैं। यह निर्णय इसलिए किया गया क्योंकि जावा जेनरिक उस टुकड़े में इतनी देरी से आया था कि वे पिछड़ी संगतता को तोड़ना नहीं चाहते थे ( Map<String, String>जब भी Mapयह कहा जाता है तो यह प्रयोग करने योग्य है)। इसकी तुलना .Net / C # से करें जहां टाइप इरेज़र का उपयोग नहीं किया जाता है, जो सभी प्रकार के अंतर की ओर जाता है (जैसे कि आप आदिम प्रकारों का उपयोग कर सकते हैं IEnumerableऔर IEnumerable<T>एक दूसरे से कोई संबंध नहीं रख सकते हैं )।

और जावा 5+ संकलक के साथ संकलित जेनरिक का उपयोग करने वाला एक वर्ग JDK 1.4 पर प्रयोग करने योग्य है (यह मानते हुए कि जावा 5+ की आवश्यकता वाले अन्य सुविधाओं या वर्गों का उपयोग नहीं करता है)।

इसीलिए जावा जेनरिक को सिंटैक्टिक शुगर कहा जाता है ।

लेकिन जेनरिक कैसे करें इस निर्णय का गहरा प्रभाव इतना है कि जावा जेनरिक एफएक्यू एफएक्यू ने कई लोगों के जावा जेनरिक के बारे में कई सवालों के जवाब दिए हैं।

C ++ टेम्प्लेट में कई विशेषताएं होती हैं, जो Java Generics नहीं करती हैं:

  • आदिम प्रकार के तर्कों का उपयोग।

    उदाहरण के लिए:

    template<class T, int i>
    class Matrix {
      int T[i][i];
      ...
    }

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

  • डिफ़ॉल्ट प्रकार के तर्कों का उपयोग , जो कि एक विशेषता है जो मुझे जावा में याद आती है, लेकिन इसके लिए पश्चगामी संगतता कारण हैं;

  • जावा तर्क वितर्क करने की अनुमति देता है।

उदाहरण के लिए:

public class ObservableList<T extends List> {
  ...
}

यह वास्तव में जोर देने की आवश्यकता है कि विभिन्न तर्कों के साथ टेम्प्लेट इनवोकेशन वास्तव में अलग-अलग प्रकार के होते हैं। वे स्थैतिक सदस्यों को भी साझा नहीं करते हैं। जावा में ऐसा नहीं है।

संपूर्णता के लिए, जेनेरिक के साथ मतभेदों के अलावा, यहां C ++ और जावा (और एक अन्य ) की एक बुनियादी तुलना है

और मैं Java में Thinking का सुझाव भी दे सकता हूँ । C ++ प्रोग्रामर के रूप में बहुत सी अवधारणाएं ऑब्जेक्ट्स की तरह होंगी, जो पहले से ही दूसरी प्रकृति होगी लेकिन सूक्ष्म अंतर हैं इसलिए यह एक परिचयात्मक पाठ के लिए सार्थक हो सकता है भले ही आप भागों को स्किम करते हों।

जावा सीखते समय आप जो कुछ भी सीखेंगे, वह सभी पुस्तकालयों (दोनों मानक - जेडीके में आता है - और गैर-मानक है, जिसमें आमतौर पर स्प्रिंग जैसी चीजें शामिल हैं)। जावा सिंटैक्स C ++ सिंटैक्स की तुलना में अधिक क्रियाशील है और इसमें बहुत सी C ++ विशेषताएँ नहीं हैं (जैसे ऑपरेटर ओवरलोडिंग, मल्टीपल इनहेरिटेंस, डिस्ट्रॉक्टर मैकेनिज़्म आदि), लेकिन यह कड़ाई से इसे C ++ का सबसेट नहीं बनाता है।


1
वे अवधारणा में समकक्ष नहीं हैं। सबसे अच्छा उदाहरण है क्यूरेटिंग आवर्ती टेम्पलेट पैटर्न। दूसरा सबसे अच्छा नीति उन्मुख डिजाइन। तीसरा सबसे अच्छा तथ्य यह है कि C ++ कोण कोष्ठक (myArray <5>) में अभिन्न संख्याओं को पारित करने की अनुमति देता है।
मैक्स लाइबबर्ट

1
नहीं, वे अवधारणा के समकक्ष नहीं हैं। अवधारणा में कुछ ओवरलैप है, लेकिन ज्यादा नहीं। दोनों आपको सूची <T> बनाने की अनुमति देते हैं, लेकिन यह जहाँ तक जाता है। C ++ टेम्प्लेट बहुत आगे जाते हैं।
१al:०४

5
यह नोट करना महत्वपूर्ण है कि टाइप इरेज़र इश्यू का मतलब केवल बैकवर्ड कंपेटिबिलिटी से अधिक है Map map = new HashMap<String, String>। इसका मतलब है कि आप एक पुराने JVM पर नए कोड को तैनात कर सकते हैं और यह bytecode में समानता के कारण चलेगा।
युवल एडम

1
आप ध्यान दें कि मैंने कहा था "मूल रूप से एक महिमामंडित प्रीप्रोसेसर / मैक्रो"। यह एक सादृश्य था क्योंकि प्रत्येक टेम्पलेट घोषणा अधिक कोड बनाएगी (जावा / सी # के विपरीत)।
cletus

4
टेम्पलेट कोड कॉपी-एंड-पेस्ट की तुलना में बहुत अलग है। यदि आप स्थूल विस्तार के बारे में सोचते हैं, तो जल्दी या बाद में आप इस तरह के एक के रूप में सूक्ष्म कीड़ों की चपेट में आ जाएंगे
Nemanja Trifunovic

86

C ++ में टेम्प्लेट हैं। जावा में जेनेरिक हैं, जो C ++ टेम्प्लेट की तरह थोड़े सॉर्ट करते हैं, लेकिन वे बहुत, बहुत अलग हैं।

टेम्पलेट काम करते हैं, जैसा कि नाम का तात्पर्य है, कंपाइलर को (इसके लिए प्रतीक्षा करें ...) टेम्प्लेट प्रदान करके, जिसका उपयोग वह टेम्प्लेट मापदंडों में भरकर टाइप-सेफ कोड जनरेट करने के लिए कर सकता है।

जेनरिक, जैसा कि मैं उन्हें समझता हूं, दूसरे तरीके से काम करते हैं: कंपाइलर द्वारा टाइप पैरामीटर का उपयोग यह सत्यापित करने के लिए किया जाता है कि उनका उपयोग करने वाला कोड टाइप-सुरक्षित है, लेकिन परिणामी कोड बिना किसी प्रकार के उत्पन्न होता है।

C ++ टेम्प्लेट को वास्तव में अच्छा मैक्रो सिस्टम के रूप में सोचें , और जावा जेनरिक स्वचालित रूप से टाइपकास्ट उत्पन्न करने के लिए एक उपकरण के रूप में।

 


4
यह एक बहुत अच्छा, संक्षिप्त विवरण है। एक ट्वीक मैं ऐसा करने के लिए ललचाऊंगा कि जावा जेनरिक स्वचालित रूप से टाइपकास्ट उत्पन्न करने के लिए एक उपकरण है जो सुरक्षित होने की गारंटी देता है (कई शर्तों के साथ)। कुछ मायनों में वे C ++ से संबंधित हैं const। C ++ में किसी ऑब्जेक्ट को एक constपॉइंटर के माध्यम से तब तक संशोधित नहीं किया जाएगा जब तक कि const-नेस दूर नहीं डाली जाती। इसी तरह, जावा में जेनेरिक प्रकारों द्वारा बनाई गई निहित जातियों को "सुरक्षित" होने की गारंटी दी जाती है, जब तक कि प्रकार के पैरामीटर मैन्युअल रूप से कोड में कहीं दूर नहीं डाले जाते हैं।
लारेंस गोन्साल्वेस

16

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


1
+1 टेम्पलेट विशेषज्ञता संकलन-समय मेटाप्रोग्रामिंग के लिए अविश्वसनीय रूप से महत्वपूर्ण है - यह अंतर अपने आप में जावा जेनरिक बनाता है जो बहुत कम शक्तिशाली है
फैसल वली

13

जावा जेनेरिक एंड कलेक्शंस बाय मौरिस नेफ्टलिन, फिलिप वाडलर में इस विषय की बहुत व्याख्या है । इस पुस्तक की पुरजोर सिफारिश की जाती है। उद्धरण के लिए:

जावा में जेनेरिक, C ++ में टेम्पलेट से मिलते जुलते हैं। ... वाक्य-विन्यास जानबूझकर समान है और शब्दार्थ जानबूझकर अलग हैं। ... शब्दार्थ, जावा जेनरिक को एरेस्योर द्वारा परिभाषित किया गया है, जहां C ++ टेम्प्लेट विस्तार द्वारा परिभाषित किए गए हैं।

कृपया पूरा विवरण यहाँ पढ़ें ।

वैकल्पिक शब्द
(स्रोत: अजवायन.कॉम )


5

मूल रूप से, AFAIK, C ++ टेम्प्लेट प्रत्येक प्रकार के लिए कोड की एक प्रति बनाते हैं, जबकि जावा जेनरिक बिल्कुल उसी कोड का उपयोग करते हैं।

हां, आप कह सकते हैं कि C ++ टेम्प्लेट जावा जेनेरिक कॉन्सेप्ट के बराबर है (हालांकि यह कहना ठीक होगा कि जावा जेनेरिक कॉन्सेप्ट में C ++ के बराबर हैं)

यदि आप C ++ के टेम्पलेट तंत्र से परिचित हैं, तो आप सोच सकते हैं कि जेनेरिक समान हैं, लेकिन समानता सतही है। जेनरिक प्रत्येक विशेषज्ञता के लिए एक नया वर्ग उत्पन्न नहीं करते हैं, न ही वे "टेम्पलेट मेटाप्रोग्रामिंग" की अनुमति देते हैं।

से: जावा पीढ़ी


3

जावा (और C #) जेनेरिक एक साधारण रन-टाइम प्रकार प्रतिस्थापन तंत्र प्रतीत होता है।
C ++ टेम्प्लेट एक संकलन-समय निर्माण है जो आपको अपनी आवश्यकताओं के अनुरूप भाषा को संशोधित करने का एक तरीका देता है। वे वास्तव में एक विशुद्ध रूप से कार्यात्मक भाषा हैं जो संकलक एक संकलन के दौरान निष्पादित करते हैं।


3

C ++ टेम्पलेट का एक और लाभ विशेषज्ञता है।

template <typename T> T sum(T a, T b) { return a + b; }
template <typename T> T sum(T* a, T* b) { return (*a) + (*b); }
Special sum(const Special& a, const Special& b) { return a.plus(b); }

अब, यदि आप बिंदुओं के साथ योग कहते हैं, तो दूसरी विधि को बुलाया जाएगा, यदि आप गैर-सूचक वस्तुओं के साथ योग कहते हैं, तो पहली विधि को बुलाया जाएगा, और यदि आप वस्तुओं के sumसाथ कॉल करते Specialहैं, तो तीसरा कहा जाएगा। मुझे नहीं लगता कि यह जावा के साथ संभव है।


2
हो सकता है क्योंकि जावा में संकेत नहीं हैं .. !! क्या आप एक बेहतर उदाहरण के साथ समझा सकते हैं?
भावुक माथुर

2

मैं इसे एक वाक्य में सम्‍मिलित करूंगा: टेम्पलेट नए प्रकार बनाते हैं, जेनेरिक मौजूदा प्रकारों को प्रतिबंधित करता है।


2
आपकी व्याख्या इतनी संक्षिप्त है! और उन लोगों के लिए पूरी तरह से समझ में आता है जो विषय को अच्छी तरह समझते हैं। लेकिन जो लोग अभी तक इसे नहीं समझते हैं, उनके लिए यह बहुत मदद नहीं करता है। (जो एसओ पर किसी से सवाल पूछने का मामला है, उसे मिल गया?)
याकूब

1

@Keith:

यह कोड वास्तव में गलत है और इसके अलावा छोटे ग्लिट्स ( templateछोड़े गए, स्पेशलाइजेशन सिंटैक्स अलग तरह से दिखते हैं), आंशिक विशेषज्ञता फंक्शन टेम्प्लेट्स पर काम नहीं करती है, केवल क्लास टेम्प्लेट पर। कोड हालांकि, पुराने पुराने ओवरलोडिंग के बजाय आंशिक टेम्पलेट विशेषज्ञता के बिना काम करेगा:

template <typename T> T sum(T a, T b) { return a + b; }
template <typename T> T sum(T* a, T* b) { return (*a) + (*b); }

2
यह जवाब क्यों है और टिप्पणी नहीं है?
लॉरेंस गोन्साल्वेस

3
@ गौर: एक बार के लिए, क्योंकि यह स्टैक ओवरफ्लो पर टिप्पणियों को लागू करने से बहुत पहले पोस्ट किया गया था। दूसरे के लिए, क्योंकि यह न केवल एक टिप्पणी है - यह सवाल का जवाब भी है: उपरोक्त कोड जैसा कुछ जावा में संभव नहीं है।
कोनराड रुडोल्फ

1

नीचे दिया गया जवाब क्रैकिंग द कोडिंग इंटरव्यू किताब से लिया गया है सॉल्यूशंस से अध्याय 13 , जो मुझे लगता है कि बहुत अच्छा है।

जावा जेनेरिक के कार्यान्वयन को "टाइप इरेज़र:" के विचार में निहित किया गया है। यह तकनीक पैरामीटर प्रकार को समाप्त कर देती है जब स्रोत कोड जावा वर्चुअल मशीन (जेवीएम) बाइटकोड में अनुवादित होता है। उदाहरण के लिए, मान लीजिए कि आपके पास नीचे जावा सॉफ्टवेयर है:

Vector<String> vector = new Vector<String>();
vector.add(new String("hello"));
String str = vector.get(0);

संकलन के दौरान, इस कोड को फिर से लिखा गया है:

Vector vector = new Vector();
vector.add(new String("hello"));
String str = (String) vector.get(0);

जावा जेनरिक का उपयोग वास्तव में हमारी क्षमताओं के बारे में ज्यादा नहीं बदला है; यह सिर्फ चीजों को थोड़ा चौकस कर देता है। इस कारण से, जावा जेनरिक को कभी-कभी "सिंटैक्टिक शुगर: 'कहा जाता है।

यह C ++ से काफी अलग है। C ++ में, टेम्पलेट अनिवार्य रूप से एक गौरवशाली मैक्रो सेट है, जिसमें कंपाइलर प्रत्येक प्रकार के लिए टेम्प्लेट कोड की एक नई प्रतिलिपि बनाता है। इस बात का प्रमाण इस तथ्य में है कि MyClass का एक उदाहरण स्थिर चर withMyClass को साझा नहीं करेगा। हालाँकि, MyClass के टाव इंस्टेंस एक स्थिर चर साझा करेंगे।

/*** MyClass.h ***/
 template<class T> class MyClass {
 public:
 static int val;
 MyClass(int v) { val v;}
 };
 /*** MyClass.cpp ***/
 template<typename T>
 int MyClass<T>::bar;

 template class MyClass<Foo>;
 template class MyClass<Bar>;

 /*** main.cpp ***/
 MyClass<Foo> * fool
 MyClass<Foo> * foo2
 MyClass<Bar> * barl
 MyClass<Bar> * bar2

 new MyClass<Foo>(10);
 new MyClass<Foo>(15);
 new MyClass<Bar>(20);
 new MyClass<Bar>(35);
 int fl fool->val; // will equal 15
 int f2 foo2->val; // will equal 15
 int bl barl->val; // will equal 35
 int b2 bar2->val; // will equal 35

जावा में, स्थिर चर को MyClass के उदाहरणों में साझा किया जाता है, चाहे वह ff स्तंभ प्रकार के मापदंडों की परवाह किए बिना हो।

जावा जेनरिक और C ++ टेम्प्लेट में कई अन्य अंतर हैं। इसमें शामिल है:

  • C ++ टेम्पलेट आदिम प्रकार का उपयोग कर सकते हैं, जैसे int। जावा इंटेगर का उपयोग नहीं कर सकता है।
  • जावा में, आप टेम्पलेट के प्रकार के मापदंडों को एक निश्चित प्रकार के होने के लिए प्रतिबंधित कर सकते हैं। उदाहरण के लिए, आप एक CardDeck को लागू करने के लिए जेनरिक का उपयोग कर सकते हैं और निर्दिष्ट कर सकते हैं कि टाइप पैरामीटर CardGame से विस्तारित होना चाहिए।
  • C ++ में, टाइप पैरामीटर को तत्काल किया जा सकता है, जबकि जावा इसका समर्थन नहीं करता है।
  • जावा में, टाइप पैरामीटर (यानी, Foo in MyClass) का उपयोग स्थिर तरीकों और चर के लिए नहीं किया जा सकता है, क्योंकि ये MyClass और MyClass के बीच साझा किए जाएंगे। C ++ में, ये कक्षाएं di ent erent हैं, इसलिए प्रकार पैरामीटर का उपयोग स्थिर विधियों और चर के लिए किया जा सकता है।
  • जावा में, MyClass के सभी उदाहरण, उनके प्रकार के मापदंडों की परवाह किए बिना, एक ही प्रकार के हैं। प्रकार पैरामीटर को रनटाइम पर मिटा दिया जाता है। C ++ में, विभिन्न प्रकार के मापदंडों वाले उदाहरण di types erent प्रकार हैं।

0

टेम्पलेट एक मैक्रो सिस्टम के अलावा और कुछ नहीं है। सिंटेक्स शुगर। वे वास्तविक संकलन से पहले पूरी तरह से विस्तारित हैं (या, कम से कम, संकलक व्यवहार करते हैं जैसे कि मामला था)।

उदाहरण:

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

जावा में आप कुछ इस तरह से कर सकते हैं:

import java.io.*;
interface ScalarProduct<A> {
    public Integer scalarProduct(A second);
}
class Nil implements ScalarProduct<Nil>{
    Nil(){}
    public Integer scalarProduct(Nil second) {
        return 0;
    }
}
class Cons<A implements ScalarProduct<A>> implements ScalarProduct<Cons<A>>{
    public Integer value;
    public A tail;
    Cons(Integer _value, A _tail) {
        value = _value;
        tail = _tail;
    }
    public Integer scalarProduct(Cons<A> second){
        return value * second.value + tail.scalarProduct(second.tail);
    }
}
class _Test{
    public static Integer main(Integer n){
        return _main(n, 0, new Nil(), new Nil());
    }
    public static <A implements ScalarProduct<A>> 
      Integer _main(Integer n, Integer i, A first, A second){
        if (n == 0) {
            return first.scalarProduct(second);
        } else {
            return _main(n-1, i+1, 
                         new Cons<A>(2*i+1,first), new Cons<A>(i*i, second));
            //the following line won't compile, it produces an error:
            //return _main(n-1, i+1, first, new Cons<A>(i*i, second));
        }
    }
}
public class Test{
    public static void main(String [] args){
        System.out.print("Enter a number: ");
        try {
            BufferedReader is = 
              new BufferedReader(new InputStreamReader(System.in));
            String line = is.readLine();
            Integer val = Integer.parseInt(line);
            System.out.println(_Test.main(val));
        } catch (NumberFormatException ex) {
            System.err.println("Not a valid number");
        } catch (IOException e) {
            System.err.println("Unexpected IO ERROR");
        }
    }
}

C # में आप लगभग एक ही बात लिख सकते हैं। C ++ में इसे फिर से लिखने की कोशिश करें, और यह टेम्पलेट्स के अनंत विस्तार के बारे में शिकायत करते हुए, संकलन नहीं करेगा।


ठीक है, यह 3 साल पुराना है, लेकिन मैं वैसे भी जवाब दे रहा हूं। मैं आपकी बात नहीं देखता। संपूर्ण कारण जावा उस टिप्पणी की गई लाइन के लिए एक त्रुटि उत्पन्न करता है क्योंकि आप एक ऐसे फ़ंक्शन को कॉल करेंगे जो दो ए की विभिन्न तर्क (ए और विपक्ष <A>) के साथ उम्मीद करता है और यह वास्तव में बुनियादी है और ऐसा तब भी होता है जब कोई जेनरिक शामिल नहीं होता है। सी ++ वह भी करता है। इसके अलावा, इस कोड ने मुझे कैंसर दिया क्योंकि यह वास्तव में भयानक है। हालाँकि, आप इसे अभी भी सी ++ में ऐसा ही करेंगे, इसलिए आपको पाठ्यक्रम में संशोधन करना होगा क्योंकि सी ++ जावा नहीं है, लेकिन यह सी ++ के टेम्प्लेट्स का कोई नुकसान नहीं है।
क्लॉकटाउन

@ क्लॉकटाउन नं, आप C ++ में ऐसा नहीं कर सकते। संशोधनों की कोई राशि की अनुमति नहीं होगी। और यह है कि सी ++ टेम्पलेट्स का नुकसान है।
MigMit

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

ऐसा होता है। तर्क बिल्कुल मेल नहीं खा रहे हैं क्योंकि लंबाई अलग हैं। आप C ++ में ऐसा नहीं कर सकते।
MigMit

0

मैं यहाँ askanydifference का उद्धरण देना चाहूंगा :

सी ++ और जावा के बीच मुख्य अंतर प्लेटफॉर्म पर उनकी निर्भरता में निहित है। जबकि, C ++ प्लेटफॉर्म डिपेंडेंट लैंग्वेज है, जावा प्लेटफॉर्म इंडिपेंडेंट लैंग्वेज है।

उपरोक्त कथन यही कारण है कि C ++ सही सामान्य प्रकार प्रदान करने में सक्षम है। जबकि जावा की सख्त जाँच है और इसलिए वे जेनेरिक का उपयोग करने की अनुमति नहीं देते हैं जिस तरह से सी ++ इसकी अनुमति देता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.