जावा का अंतिम बनाम C ++ का कास्ट


151

सी ++ प्रोग्रामर के लिए जावा ट्यूटोरियल कहते हैं (प्रकाश डाला अपने ही है) कि:

कीवर्ड के अंतिम है मोटे तौर पर सी में const के बराबर ++

इस संदर्भ में "मोटे तौर पर" का क्या अर्थ है? क्या वे बिल्कुल समान नहीं हैं?

यदि कोई हो, तो क्या अंतर हैं?

जवाबों:


195

C ++ में एक सदस्य फ़ंक्शन को चिह्नित करने का constमतलब है कि इसे constउदाहरणों पर बुलाया जा सकता है । जावा के पास इसके बराबर नहीं है। उदाहरण के लिए:

class Foo {
public:
   void bar();
   void foo() const;
};

void test(const Foo& i) {
   i.foo(); //fine
   i.bar(); //error
}

मूल्यों को एक बार, बाद में जावा में ही सौंपा जा सकता है जैसे:

public class Foo {
   void bar() {
     final int a;
     a = 10;
   }
}

जावा में कानूनी है, लेकिन C ++ नहीं है:

public class Foo {
   void bar() {
     final int a;
     a = 10;
     a = 11; // Not legal, even in Java: a has already been assigned a value.
   }
}

जावा और C ++ में दोनों सदस्य चर final/ constक्रमशः हो सकते हैं। वर्ग के एक उदाहरण का निर्माण पूरा होने के समय तक इन्हें एक मूल्य दिए जाने की आवश्यकता होती है।

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

public class Foo {
   private final int a;
   private final int b = 11;
   public Foo() {
      a = 10;
   }
}

C ++ में आपको constसदस्यों को एक मूल्य देने के लिए आरंभीकरण सूचियों का उपयोग करना होगा :

class Foo {
   const int a;
public:
   Foo() : a(10) {
      // Assignment here with = would not be legal
   }
};

जावा फाइनल में नॉन-ओवरड्रिबल के रूप में चीजों को चिह्नित करने के लिए इस्तेमाल किया जा सकता है। C ++ (Pre-C ++ 11) ऐसा नहीं करता है। उदाहरण के लिए:

public class Bar {
   public final void foo() {
   }
}

public class Error extends Bar {
   // Error in java, can't override
   public void foo() {
   }
}

लेकिन C ++ में:

class Bar {
public:
   virtual void foo() const {
   }
};

class Error: public Bar {
public:
   // Fine in C++
   virtual void foo() const {
   }
};

यह ठीक है, क्योंकि सदस्य फ़ंक्शन constको चिह्नित करने के शब्दार्थ अलग हैं। (आप केवल होने से भी अधिभार कर सकते हैंconst सदस्य कार्यों में से एक पर । (यह भी ध्यान रखें कि C ++ 11 सदस्य कार्यों को अंतिम रूप से चिह्नित करने की अनुमति देता है, C ++ 11 अद्यतन अनुभाग देखें)


C ++ 11 अपडेट:

C ++ 11 वास्तव में आपको finalजावा में समान सुविधा के समान समान शब्दार्थ के साथ, दोनों वर्गों और सदस्य कार्यों को चिह्नित करने की अनुमति देता है :

public class Bar {
   public final void foo() {
   }
}

public class Error extends Bar {
   // Error in java, can't override
   public void foo() {
   }
}

अब इसे C ++ 11 में बिल्कुल लिखा जा सकता है:

class Bar {
public:
  virtual void foo() final;
};

class Error : public Bar {
public:
  virtual void foo() final;
};

मुझे इस उदाहरण को G ++ 4.7 की प्री-रिलीज़ के साथ संकलित करना था। ध्यान दें कि यह constइस मामले में प्रतिस्थापित नहीं करता है , बल्कि इसे संवर्धित करता है, जावा-जैसा व्यवहार प्रदान करता है जिसे निकटतम समकक्ष C ++ कीवर्ड के साथ नहीं देखा गया था। इसलिए यदि आप चाहते हैं कि एक सदस्य समारोह दोनों हो finalऔर constआप करेंगे:

class Bar {
public:
  virtual void foo() const final;
};

(के आदेश constऔरfinal यहाँ के आवश्यकता है)।

पहले constसदस्य कार्यों का एक सीधा समकक्ष नहीं था, हालांकि कार्यों को गैर- virtualसंकलित करना एक संभावित विकल्प होगा, हालांकि संकलन समय पर त्रुटि पैदा किए बिना।

इसी तरह जावा:

public final class Bar {
}

public class Error extends Bar {
}

C ++ 11 में हो जाता है:

class Bar final {
};

class Error : public Bar {
};

(पहले के privateकंस्ट्रक्टर संभवतः निकटतम थे जिन्हें आप C ++ में प्राप्त कर सकते थे)

दिलचस्प है, पूर्व-सी ++ 11 कोड के साथ पीछे की संगतता बनाए रखने के लिए सामान्य तरीके से एक कीवर्ड final नहीं है। ( struct final;यह देखें कि तुच्छ, कानूनी C ++ 98 का ​​उदाहरण यह देखने के लिए है कि क्यों यह एक कीवर्ड कोड को तोड़ देगा)


3
आपको उन तरीकों को आभासी बनाना चाहिए; अन्यथा, आप वास्तव में एक ही काम नहीं कर रहे हैं
ब्लूराजा - डैनी पफ्लुगुफ्ट

1
अपने अंतिम उदाहरण में, आपके पास जो भी है वह कानूनी है, लेकिन यह ध्यान देने योग्य है कि final int a; a = 10; a = 11;यह ( finalवैरिएबल संशोधक के रूप में इसका उद्देश्य नहीं है ।) इसके अलावा, अंतिम सदस्यों को एक वर्ग केवल घोषणा के समय, या एक बार एक कंस्ट्रक्टर में सेट किया जा सकता है। ।
corsiKa

2
ध्यान दें कि C ++ 0x finalइस सटीक उद्देश्य के लिए सदस्य फ़ंक्शन डेकोरेटर जोड़ता है । VC ++ 2005, 2008 और 2010 पहले से ही लागू किया गया है, sealedइसके बजाय प्रासंगिक कीवर्ड का उपयोग करते हुए final

@ildjarn -that के बारे में जानना दिलचस्प है और फिर भी एक और अपेक्षाकृत छोटा C ++ 0x परिवर्तन जो मुझे पता नहीं था! मैं शायद पाठ में कहीं एक छोटी टिप्पणी जोड़ूंगा जो यह दर्शाता है कि यह C ++ 0x के साथ बदल रहा है।
फ्लेक्सो

1
जाहिरा तौर पर लोग अभी भी परिणाम के रूप में अंतिम संचयकर्ता के साथ कोडबेस में अभी भी एस / कॉन्स्ट / फाइनल / जी करते हैं!
फ्लेक्सो

30

जावा में अंतिम कीवर्ड का इस्तेमाल चार चीजों के लिए किया जा सकता है:

  • एक वर्ग या विधि पर इसे सील करने के लिए (कोई उपवर्ग / ओवरराइडिंग की अनुमति नहीं)
  • एक सदस्य चर पर यह घोषित करने के लिए कि यह ठीक एक बार सेट किया जा सकता है (मुझे लगता है कि यह वही है जिसके बारे में आप बात कर रहे हैं)
  • एक विधि में घोषित चर पर, यह सुनिश्चित करने के लिए कि यह बिल्कुल एक बार सेट किया जा सकता है
  • एक विधि पैरामीटर पर, यह घोषित करने के लिए कि इसे विधि के भीतर संशोधित नहीं किया जा सकता है

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

एक सदस्य चर फाइनल बनाने का एक और परिणाम मेमोरी मॉडल से संबंधित है, जो कि यदि आप थ्रेडेड वातावरण में काम करते हैं तो यह महत्वपूर्ण है।


'मेमोरी मॉडल' कहने का क्या मतलब है? मुझे नहीं मिला।
टोनी

1
@ टिप्पणी: जावा भाषा विशिष्टता, अध्याय १ony.४। मेमोरी मॉडल - docs.oracle.com/javase/specs/jls/se8/html/index.html - googles पहली हिट
राल्फ

27

एक constऑब्जेक्ट केवल constतरीकों को कॉल कर सकता है , और आमतौर पर अपरिवर्तनीय माना जाता है।

const Person* person = myself;
person = otherPerson; //Valid... unless we declared it const Person* const!
person->setAge(20); //Invalid, assuming setAge isn't a const method (it shouldn't be)

एक finalवस्तु को एक नई वस्तु पर सेट नहीं किया जा सकता है, लेकिन यह अपरिवर्तनीय नहीं है - किसी को भी किसी भी setतरीके को कॉल करने से रोकना नहीं है ।

final Person person = myself;
person = otherPerson; //Invalid
person.setAge(20); //Valid!

जावा के पास वस्तुओं को अपरिवर्तनीय घोषित करने का कोई अंतर्निहित तरीका नहीं है; आपको अपने आप को कक्षा को अपरिवर्तनीय बनाने की आवश्यकता है।

जब चर एक आदिम प्रकार है, final/ constएक ही काम करते हैं।

const int a = 10; //C++
final int a = 10; //Java
a = 11; //Invalid in both languages

3
यह एक महान जवाब है, भी (यहां कई अन्य लोगों की तरह)। दुर्भाग्य से, मैं केवल एक उत्तर को स्वीकार कर सकता हूं। :)
विनविन

1
एकदम सही जवाब!
ADJ

13

जावा फाइनल आदिम मूल्य प्रकारों पर C ++ कॉन्स्टिट्यूशन के बराबर है।

जावा संदर्भ प्रकारों के साथ, अंतिम कीवर्ड एक कास्ट पॉइंटर के बराबर है ... अर्थात

//java
final int finalInt = 5;
final MyObject finalReference = new MyObject();

//C++
const int constInt = 5;
MyObject * const constPointer = new MyObject();

"अंतिम कीवर्ड एक कास्ट पॉइंटर के बराबर है" अच्छी तरह से कहा
ADJ

8

आपके पास पहले से ही कुछ शानदार जवाब हैं, लेकिन एक बिंदु जो जोड़ने के लायक लग रहा था: constC ++ आमतौर पर वस्तुओं के राज्य को बदलने वाले कार्यक्रम के अन्य हिस्सों को रोकने के लिए उपयोग किया जाता है। जैसा कि बताया गया है, finalजावा में ऐसा नहीं हो सकता है (आदिम को छोड़कर) - यह सिर्फ संदर्भ को एक अलग ऑब्जेक्ट में बदलने से रोकता है । लेकिन अगर आप एक का उपयोग कर रहे हैं Collection, तो आप स्थैतिक विधि का उपयोग करके अपनी वस्तुओं में परिवर्तन को रोक सकते हैं

 Collection.unmodifiableCollection( myCollection ) 

यह एक Collectionसंदर्भ देता है जो तत्वों को रीड-एक्सेस प्रदान करता है, लेकिन एक अपवाद फेंकता है यदि संशोधनों का प्रयास किया जाता है, तो यह constC ++ में थोड़ा सा होता है


8

जावा के final केवल आदिम प्रकारों और संदर्भों पर काम करता है, कभी भी ऑब्जेक्ट पर नहीं होता है जहाँ कॉन्स्टेबल कीवर्ड किसी भी चीज़ पर काम करता है।

तुलना const list<int> melist;के साथ final List<Integer> melist;पहले बनाता है यह असंभव सूची को संशोधित करने के लिए, जबकि बाद ही करने के लिए एक नई सूची बताए से आप बंद हो जाता है melist


3

कुछ निश्चित और सूक्ष्म बहु-थ्रेडिंग गुणों के अलावा , घोषित किए गए चर finalको घोषणा पर आरंभ करने की आवश्यकता नहीं है!

अर्थात यह जावा में मान्य है:

// declare the variable
final int foo;

{
    // do something...

    // and then initialize the variable
    foo = ...;
}

यह मान्य नहीं होगा यदि C ++ के साथ लिखा जाए const


2

विकिपीडिया के अनुसार :

  • C ++ में, एक कास्ट फ़ील्ड को केवल पुन: असाइन किए जाने से सुरक्षित नहीं किया जाता है, लेकिन अतिरिक्त सीमा होती है कि केवल कॉन्स्टेड विधियों को इस पर कॉल किया जा सकता है और इसे केवल अन्य विधियों के कॉन्स्ट तर्क के रूप में पारित किया जा सकता है।
  • गैर-स्थैतिक आंतरिक कक्षाएं स्वतंत्र रूप से एन्क्लोजिंग वर्ग के किसी भी क्षेत्र तक पहुंच सकती हैं, अंतिम या नहीं।

1
शब्द 'पुन: असाइन किया गया' शब्द उस पृष्ठ के वर्तमान संस्करण में नहीं दिखता है, और न ही आपके दूसरे बिंदु से मिलता-जुलता कुछ भी है, जो या तो गलत है या अप्रासंगिक है, जो कि 'एक्सेस' से आपके मतलब के आधार पर है। Is नॉन-स्टैटिक इनर ’डबल टॉक है। विकिपीडिया C ++ या जावा के लिए एक आदर्श संदर्भ नहीं है।
लोर्ने

2

मैं अनुमान लगा रहा हूं कि यह "मोटे तौर पर" कहता है क्योंकि constसी ++ का अर्थ जटिल हो जाता है जब आप पॉइंटर्स, यानी निरंतर पॉइंटर्स बनाम पॉइंटर्स टू कंटेंट की बात करते हैं। चूंकि जावा में कोई "स्पष्ट" संकेत finalनहीं हैं, इसलिए इन मुद्दों पर नहीं है।


1

मुझे समझाएं कि मैंने स्विच / केस स्टेटमेंट के उदाहरण के साथ क्या समझा।

प्रत्येक केस स्टेटमेंट के मानों को स्विच वैल्यू के समान समय-समय पर एक ही डेटा प्रकार के निरंतर मूल्यों को संकलित करना चाहिए।

नीचे की तरह कुछ घोषित करें (या तो आपकी विधि में स्थानीय उदाहरणों के रूप में, या आपकी कक्षा में स्थिर चर के रूप में (तब इसे स्थिर जोड़ें), या एक उदाहरण चर।

final String color1 = "Red";

तथा

static final String color2 = "Green";

switch (myColor) { // myColor is of data type String
    case color1:
    //do something here with Red
    break;
    case color2:
    //do something with Green
    break;
}

यह कोड संकलित नहीं करेगा, यदि color1एक वर्ग / उदाहरण चर है और स्थानीय चर नहीं है। यह संकलित करेगा यदि color1इसे स्थिर अंतिम के रूप में परिभाषित किया गया है (तब यह स्थिर अंतिम चर बन जाता है)।

जब यह संकलित नहीं होता है, तो आपको निम्न त्रुटि मिलेगी

error: constant string expression required

-7

कीवर्ड "कॉन्स्ट" का अर्थ है कि आपका चर ROM (माइक्रोप्रोसेसर के साथ) में सहेजा गया है। कंप्यूटर में, आपके चर को असेंबली कोड (केवल रैम पढ़ें) के लिए रैम क्षेत्र में सहेजा जाता है। इसका अर्थ है कि आपका चर लेखन योग्य रैम में शामिल नहीं है: स्थिर मेमोरी, स्टैक मेमोरी और हीप मेमोरी।

कीवर्ड "फाइनल" का अर्थ है कि आपका चर लेखन योग्य रैम में सहेजा गया है, लेकिन आप संकलक को नोटिस करते हैं कि आपका चर केवल एक बार ही बदला गया है।

//in java language you can use:
static final int i =10;
i =11; //error is showed here by compiler

//the same in C++ the same as follows
int i =10;
const int &iFinal = i;

iFinal = 11; //error is showed here by compiler the same as above

मुझे लगता है, "कॉन्स्ट" प्रदर्शन में खराब है, इसलिए जावा इसका उपयोग नहीं करता है।

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