2009-09-02 16 views
32

अस्वीकरण: मुझे पता है कि कॉन्स्ट-शुद्धता की उपयोगिता के बारे में दो प्रश्न हैं, हालांकि, किसी ने भी चर्चा नहीं की कि सी ++ में अन्य प्रोग्रामिंग भाषाओं के विपरीत कॉन्स्ट-शुद्धता आवश्यक है। इसके अलावा, मैं इन सवालों के जवाब दिए गए उत्तरों से संतुष्ट नहीं हूं।सी ++ के लिए विशिष्ट कॉन्स्ट-क्वालिटी क्यों है?

मैंने अब कुछ प्रोग्रामिंग भाषाओं का उपयोग किया है, और एक चीज जो मुझे सी ++ में बग करता है वह कॉन्स्ट-शुद्धता की धारणा है। जावा, सी #, पायथन, रूबी, विजुअल बेसिक इत्यादि में ऐसी कोई धारणा नहीं है, यह सी ++ के लिए बहुत विशिष्ट है।

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

मुझे आश्चर्य है कि सी ++ में यह क्या है जो अन्य प्रोग्रामिंग भाषाओं के विपरीत आवश्यक है,

अब तक, मैं केवल एक मामले में जहां स्थिरांक इस्तेमाल किया जाना चाहिए देखा है:

#include <iostream> 

struct Vector2 { 
    int X; 
    int Y; 
}; 

void display(/* const */ Vector2& vect) { 
    std::cout << vect.X << " " << vect.Y << std::endl; 
} 

int main() { 
    display(Vector2()); 
} 

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

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

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

एंडर्स हेल्स्बर्ग (सी # वास्तुकार), CLR Design Choices

+34

हेजल्सबर्ग पूरी तरह से सही नहीं है (सामान्य रूप से, गैर-सी ++ प्रोग्रामर पर भरोसा न करें, सी ++ डिज़ाइन निर्णयों के बारे में तर्कसंगत बनाने के लिए। यह हमेशा गलत होता है)। सी ++ आपको आसानी से कॉन्स्टेस को दूर करने की अनुमति नहीं देता है। यदि एक चर को कॉन्स के रूप में घोषित किया जाता है, तो यह * स्थिर रहता है, और आपको स्थिरता को दूर करने की अनुमति नहीं है। लेकिन यदि आप एक गैर-कॉन्स ऑब्जेक्ट लेते हैं, जो पूरी तरह से कॉन्स को बढ़ावा देता है, तो आपको कॉन्स्टेस को दूर करने की अनुमति है। – jalf

+4

नई डी भाषा में सी ++ में कॉन्स जैसी कई कार्यात्मक संरचनाएं हैं। आजकल ओओपी अतिरंजित है। – GogaRieger

+1

मुझे लगता है कि एंडर्स के पास एक बिंदु है: आपको हमेशा कॉन्स को दूर करने की अनुमति दी जाती है। यदि वस्तु वास्तव में स्थिर है तो आपको इसे लिखने की अनुमति नहीं है। मेरे छोटे जीवन में एक सी ++ प्रोग्रामर के रूप में मेरे पास केवल एक अवसर था जहां मुझे दूर कास्ट करने की आवश्यकता थी ('wxStyledTextCtrl' में इसकी सभी 'GetXXX' विधियां गैर-कॉन्स हैं!)। अगर सी ++ ने मुझे ऐसा करने की अनुमति नहीं दी, तो मैं उस क्रैपी एपीआई से फंस गया होता और इसे अपने क्लास डिज़ाइन को संक्रमित करने देता। –

उत्तर

8

ठीक है, मुझे वास्तव में समझने के लिए 6 साल लग गए होंगे, लेकिन अब मैं अंततः अपने प्रश्न का उत्तर दे सकता हूं।

कारण सी ++ "स्थिरांक-शुद्धता" है और है कि जावा, सी #, आदि नहीं करते हैं, कि सी ++ केवल मूल्य प्रकार का समर्थन करता है, और इन अन्य भाषाओं केवल समर्थन या संदर्भ प्रकार लिए कम से कम डिफ़ॉल्ट है ।

चलिए देखते हैं कि सी #, एक भाषा जो संदर्भ प्रकारों के लिए डिफ़ॉल्ट है, मूल्य प्रकार शामिल होने पर अपरिवर्तनीयता से संबंधित है।

struct Vector { 
    public int X { get; private set; } 
    public int Y { get; private set; } 
    public void Add(int x, int y) { 
     X += x; 
     Y += y; 
    } 
} 

class Foo { 
    readonly Vector _v; 
    public void Add(int x, int y) => _v.Add(x, y); 
    public override string ToString() => $"{_v.X} {_v.Y}"; 
} 

void Main() 
{ 
    var f = new Foo(); 
    f.Add(3, 4); 
    Console.WriteLine(f); 
} 

इस कोड को क्या करना चाहिए: मान लीजिए कि आप एक परिवर्तनशील मान प्रकार, और एक अन्य प्रकार के उस प्रकार के केवल पढ़ने के लिए क्षेत्र है कि करते हैं?

  1. संकलित करने के लिए
  2. प्रिंट "3, 4"
  3. प्रिंट "0, 0"

जवाब # 3 है असफल। सी # विधि का आह्वान करके अपने "पठनीय" कीवर्ड का सम्मान करने की कोशिश करता है वस्तु की एक फेंक-प्रति प्रतिलिपि पर जोड़ें। यह अजीब है, हाँ, लेकिन इसके पास अन्य विकल्प क्या हैं? यदि यह मूल वेक्टर पर विधि का आह्वान करता है, तो ऑब्जेक्ट बदल जाएगा, क्षेत्र की "केवल पढ़ने योग्य" का उल्लंघन करेगा। यदि यह संकलित करने में विफल रहता है, तो केवल मान प्रकार के सदस्य बहुत बेकार हैं, क्योंकि आप उन पर किसी भी तरीके का आह्वान नहीं कर सकते हैं, डर से वे वस्तु को बदल सकते हैं।

अगर केवल हम लेबल कर सकते हैं जो केवल पढ़ने के उदाहरणों पर कॉल करने के लिए सुरक्षित हैं ... प्रतीक्षा करें, यह बिल्कुल सही है कि सी ++ में कौन सी कॉन्स विधियां हैं!

सी # कॉन्स्ट विधियों से परेशान नहीं है क्योंकि हम मूल्य प्रकारों का उपयोग नहीं करते हैं जो सी # में बहुत अधिक हैं; हम केवल परिवर्तनीय मूल्य प्रकारों से बचें (और उन्हें "बुराई" घोषित करें, 1, 2 देखें)।

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

सी ++ में "संदर्भ प्रकार" की अवधारणा नहीं है, केवल "मूल्य प्रकार" (सी # -लिंगो में); इनमें से कुछ मान प्रकार पॉइंटर्स या संदर्भ हो सकते हैं, लेकिन सी # में मूल्य प्रकारों की तरह, उनमें से कोई भी का अपना संग्रहण नहीं है। यदि सी ++ ने अपने प्रकारों पर "कॉन्स" का इलाज किया है, जिस तरह से सी # मूल्य प्रकारों पर "रीडोनली" का व्यवहार करता है, तो यह बहुत भ्रमित होगा क्योंकि उपर्युक्त उदाहरण दर्शाता है, कॉपी कन्स्ट्रक्टर के साथ ग़लत बातचीत को कभी न मानें।

तो सी ++ फेंकने वाली प्रतिलिपि नहीं बनाता है, क्योंकि इससे अंतहीन दर्द होता है। यह आपको सदस्यों पर किसी भी तरीके से कॉल करने से मना नहीं करता है, क्योंकि, अच्छी तरह से, भाषा तब बहुत उपयोगी नहीं होगी। लेकिन यह अभी भी "पठनीय" या "कॉन्स्ट-नेस" की कुछ धारणा चाहता है।

सी ++ आपको लेबल बनाने के माध्यम से मध्यस्थ तरीके खोजने का प्रयास करता है जो कि कॉन्स्ट सदस्यों पर कॉल करने के लिए कौन से तरीके सुरक्षित हैं, और फिर यह आपको अपने लेबलिंग में वफादार और सटीक होने के लिए भरोसा करता है और सीधे मूल वस्तुओं पर कॉल करता है। यह सही नहीं है - यह वर्बोज़ है, और आपको जितना चाहें उतना ही कॉन्स्टेस का उल्लंघन करने की अनुमति है - लेकिन यह अन्य सभी विकल्पों की तुलना में तर्कसंगत रूप से बेहतर है।

1

C++ (जैसा कि मापदंडों और प्रकार घोषणाओं पर लागू) स्थिरांक कीवर्ड उनके बड़े पैर की अंगुली बंद शूटिंग और अपने पूरे पैर बाहर ले जाने से प्रोग्रामर रखने के लिए एक प्रयास है प्रक्रिया में है।

मूल विचार कुछ को "संशोधित नहीं किया जा सकता" के रूप में लेबल करना है। एक कॉन्स प्रकार संशोधित नहीं किया जा सकता है (डिफ़ॉल्ट रूप से)। एक कॉन्स पॉइंटर स्मृति में एक नए स्थान को इंगित नहीं कर सकता है। सरल, सही? ।

ठीक है, कि जहां स्थिरांक शुद्धता भूमिका शुरू होती है यहाँ संभव संयोजनों जब आप स्थिरांक का उपयोग में आप अपने आप को पा सकते हैं में से कुछ हैं:

एक स्थिरांक चर संकेत मिलता है कि डेटा चर नाम द्वारा लेबल नहीं कर सकते संशोधित किया जाना चाहिए।

एक कॉन्स्ट चर के लिए एक सूचक का अर्थ है कि सूचक संशोधित किया जा सकता है, लेकिन डेटा स्वयं नहीं कर सकता है।

एक स्थिरांक सूचक एक चर करने का तात्पर्य है कि सूचक (एक नई स्मृति स्थान को इंगित करने के लिए) संशोधित नहीं किया जा सकता है, लेकिन जो डेटा सूचक अंक संशोधित किया जा सकता है कि।

एक स्थिरांक चर के लिए एक स्थिरांक सूचक संकेत मिलता है कि न तो सूचक है और न ही डेटा है जो इसे बिंदुओं संशोधित किया जा सकता है।

क्या आप देखते हैं कि कुछ चीजें कैसे गुम हो सकती हैं? यही कारण है कि जब आप कॉन्स का उपयोग करते हैं, तो यह सही होना महत्वपूर्ण है कि आप किस लेबल को लेबल कर रहे हैं।

बिंदु यह है कि यह सिर्फ एक संकलन-समय हैक है। लेबलिंग सिर्फ संकलक को निर्देशों की व्याख्या करने के लिए बताती है। यदि आप कॉन्स से दूर फेंकते हैं, तो आप जो भी चाहें कर सकते हैं। लेकिन आपको अभी भी उन विधियों को कॉल करना होगा जिनके पास उचित रूप से डाले गए प्रकारों के साथ स्थिरताएं होंगी।

14

कॉन्स कुछ व्यक्त करने का एक तरीका है। यह किसी भी भाषा में उपयोगी होगा, अगर आपको लगता है कि इसे व्यक्त करना महत्वपूर्ण था। उनके पास सुविधा नहीं है, क्योंकि भाषा डिजाइनरों को उन्हें उपयोगी नहीं मिला। यदि सुविधा वहां थी, तो मुझे लगता है कि यह उपयोगी होगा।

मैं जावा में फेंक विनिर्देशों की तरह सोचता हूं। यदि आप उन्हें पसंद करते हैं, तो आप शायद उन्हें अन्य भाषाओं में पसंद करेंगे। लेकिन अन्य भाषाओं के डिजाइनरों ने नहीं सोचा था कि यह महत्वपूर्ण था।

+2

चेक अपवादों के साथ समानता एक अच्छा है - आपने मुझे इसे हराया! –

+3

यह सिर पर कील हिट करता है। कॉन्स कीवर्ड प्रोग्रामर को अर्थपूर्ण अर्थ प्रदान करता है "मैं कुछ भी नहीं बदल रहा हूं!" –

4

आप वापसी मूल्य अनुकूलन का लाभ उठाने के लिए विधियों में भी कॉन्स्ट का उपयोग करना चाहते हैं। स्कॉट मेयर्स को अधिक प्रभावी सी ++ आइटम 20 देखें।

26

मुझे नहीं लगता कि किसी का दावा है कि कॉन्स्ट-शुद्धता "आवश्यक" है। लेकिन फिर, कक्षाएं वास्तव में आवश्यक नहीं हैं, क्या वे हैं? नामस्थान, अपवादों के लिए भी यही है ... आपको तस्वीर मिलती है।

कॉन्स्ट-इफेक्टनेस संकलन समय पर त्रुटियों को पकड़ने में मदद करता है, और यही कारण है कि यह उपयोगी है।

13

आप सही हैं, कॉन्स्ट-शुद्धता आवश्यक नहीं है। आप निश्चित रूप से अपने सभी कोड को कॉन्स कीवर्ड के बिना लिख ​​सकते हैं और चीजों को काम करने के लिए प्राप्त कर सकते हैं, जैसे आप जावा और पायथन में करते हैं।

लेकिन यदि आप ऐसा करते हैं, तो आपको अब कॉन्स्ट्रेंस की जांच में संकलक की सहायता नहीं मिलेगी। संकलन जो संकलक ने आपको संकलन समय के बारे में बताया होगा, अब केवल रन-टाइम पर ही मिलेगा, और यदि आपको निदान और ठीक करने में अधिक समय लगेगा।

इसलिए, कॉन्स्ट-इफेक्टनेस फीचर को विचलित करने या उससे बचने की कोशिश करना सिर्फ लंबे समय तक चीजों को कठिन बना रहा है।

61

कॉन्स्ट शुद्धता सी ++ के दो उल्लेखनीय फायदे प्रदान करती है जिन्हें मैं सोच सकता हूं, जिसमें से एक इसे अद्वितीय बनाता है।

  • यह इंटरफेस के समूह की आवश्यकता के बिना परिवर्तनीय/अपरिवर्तनीय डेटा के व्यापक विचारों की अनुमति देता है। व्यक्तिगत तरीकों को एनोटेट किया जा सकता है कि वे कॉन्स ऑब्जेक्ट्स पर चल सकते हैं या नहीं, और कंपाइलर इसे लागू करता है। हां, यह कभी-कभी परेशानी हो सकती है, लेकिन यदि आप लगातार इसका उपयोग करते हैं और const_cast का उपयोग नहीं करते हैं तो आपके पास परिवर्तनीय बनाम अपरिवर्तनीय डेटा के संबंध में कंपाइलर-चेक की गई सुरक्षा है।
  • यदि कोई ऑब्जेक्ट या डेटा आइटम const है, तो संकलक इसे केवल पढ़ने योग्य स्मृति में रखने के लिए स्वतंत्र है। यह विशेष रूप से एम्बेडेड सिस्टम में महत्वपूर्ण हो सकता है। सी ++ इसका समर्थन करता है; कुछ अन्य भाषाएं करते हैं। इसका यह भी अर्थ है कि, सामान्य स्थिति में, आप const दूर सुरक्षित रूप से नहीं डाल सकते हैं, हालांकि अभ्यास में आप अधिकांश वातावरण में ऐसा कर सकते हैं।

सी ++ एकमात्र भाषा नहीं है जिसमें स्थिरता या कुछ ऐसा है। ओकैमल और मानक एमएल की अलग-अलग शब्दावली के साथ एक समान अवधारणा है — लगभग सभी डेटा अपरिवर्तनीय (कॉन्स) है, और जब आप कुछ म्यूटेबल होना चाहते हैं तो आप इसे पूरा करने के लिए एक अलग प्रकार (ref प्रकार) का उपयोग करें। तो यह अपने पड़ोसी भाषाओं के भीतर सी ++ के लिए सिर्फ अद्वितीय है।

अंत में, दूसरी दिशा आ रही है: कई बार जावा में मैं चाहता था। final कभी-कभी स्पष्ट रूप से अपरिवर्तनीय डेटा (म्यूटेबल डेटा के विशेष रूप से अपरिवर्तनीय दृश्य) बनाने के लिए पर्याप्त नहीं जाता है, और इंटरफेस बनाना नहीं चाहता है। जावा एपीआई में अनमोडिफायबल कलेक्शन सपोर्ट को देखें और तथ्य यह है कि यह केवल रन टाइम पर जांच करता है कि क्यों कॉन्स्टेंस उपयोगी है (या कम से कम इंटरफ़ेस संरचना को सूची और उत्परिवर्तनीय सूची के लिए गहरा होना चाहिए) के उदाहरण के लिए संशोधन की अनुमति है या नहीं — ऐसा कोई कारण नहीं है कि एक अपरिवर्तनीय संरचना को बदलने का प्रयास संकलन-प्रकार त्रुटि न हो।

+0

सीधे मेरे बिंदु को संबोधित करने के लिए धन्यवाद, ये बहुत मान्य बिंदुओं की तरह दिखते हैं। +1। – Asik

+10

महत्वपूर्ण बात यह है कि यह आपको अपरिवर्तनीयता की धारणा व्यक्त करने की अनुमति देता है जिसे अन्य भाषाओं में व्यक्त नहीं किया जा सकता है (भले ही इसकी अनुशंसा की जाती है) –

+2

"अभ्यास में आप अधिकांश वातावरण में [सुरक्षित रूप से दूर कास्ट] कर सकते हैं"। बिल्कुल नहीं। 'Const' के रूप में परिभाषित ऑब्जेक्ट को संशोधित करने का यूबी उस जोखिम तक ही सीमित नहीं है जो यह रोम में हो सकता है। यदि आप 'const int i = 1 लिखते हैं; mutate ((int *) &i); std :: cout << i; 'तब संकलक को यह मानने की अनुमति है कि न तो' उत्परिवर्तन 'और न ही कार्यक्रम में कुछ और ने यूबी को' i' लिखकर उभारा है। अभ्यास में आप उम्मीद करेंगे संशोधन को उस कोड के लिए या तो सम्मानित या हानिरहित रूप से अनदेखा किया जा सकता है, लेकिन आम तौर पर सभी प्रकार की चीजें गलत हो सकती हैं जहां ऑप्टिमाइज़र ने कुछ ऐसा माना है जो सच नहीं है। –

2

सी में, जावा और सी # आप कॉल साइट को देखकर बता सकते हैं कि एक से पारित कर दिया वस्तु एक समारोह के द्वारा संशोधित किया जा सकता है:

    जावा में
  • आप जानते हैं निश्चित रूप से हो सकता है।
  • सी में आप जानते हैं कि यह केवल 'या समतुल्य हो सकता है।
  • सी # में आपको कॉल साइट पर भी 'रेफरी' कहना होगा।

सामान्य रूप से सी ++ में आप यह नहीं बता सकते हैं, क्योंकि एक गैर-कॉन्स्टेंस संदर्भ कॉल पास-दर-मान के समान दिखता है। कॉन्स संदर्भ होने से आप सी सम्मेलन को स्थापित और लागू कर सकते हैं।

यह किसी भी कोड की पठनीयता में काफी बड़ा अंतर डाल सकता है जो कार्यों को कॉल करता है। जो एक भाषा सुविधा को औचित्य देने के लिए शायद पर्याप्त है।

8

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

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

भाषा और विचार कसकर युग्मित हैं। आप जो भाषा बोलते हैं उसमें आप केवल अपने विचार व्यक्त कर सकते हैं, लेकिन भाषा आपके विचारों को भी बदलती है। तथ्य यह है कि आपके द्वारा काम की जाने वाली भाषाओं में आपके पास कॉन्स कीवर्ड नहीं है, इसका तात्पर्य है कि आपको पहले से ही एक ही समस्या के अन्य समाधान मिल चुके हैं, और वे समाधान आपके लिए प्राकृतिक प्रतीत होते हैं।

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

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

यह अवधारणा है जो मुझे अन्य भाषाओं में जाने पर अधिक याद आती है। ऐसे परिदृश्य पर विचार करें जहां आपके पास कक्षा सी है जिसमें दूसरों के बीच एक प्रकार का गुण है जो बाहरी कोड के लिए दृश्यमान होना चाहिए (आपकी कक्षा के उपयोगकर्ता ए पर कुछ जानकारी के लिए पूछने में सक्षम होना चाहिए)। यदि ए के प्रकार में कोई उत्परिवर्तन ऑपरेशन है, तो उपयोगकर्ता कोड को अपनी आंतरिक स्थिति बदलने से रोकने के लिए, आपको एक की एक प्रति बनाना होगा और इसे वापस करना होगा। कक्षा के प्रोग्रामर को पता होना चाहिए कि एक प्रतिलिपि की जानी चाहिए और (संभवतः महंगी) प्रतिलिपि करना चाहिए। दूसरी तरफ, यदि आप भाषा में निरंतरता व्यक्त कर सकते हैं, तो आप ऑब्जेक्ट के निरंतर संदर्भ (वास्तव में ऑब्जेक्ट के निरंतर दृश्य का संदर्भ) वापस कर सकते हैं और केवल आंतरिक तत्व को वापस कर सकते हैं। यह उपयोगकर्ता कोड को ऑब्जेक्ट की किसी भी विधि को कॉल करने की अनुमति देगा जिसे गैर-उत्परिवर्तनीय के रूप में चेक किया गया है, इस प्रकार आपके क्लास इनवेरिएंट को संरक्षित किया जा सकता है।

समस्या/लाभ, सभी दृष्टिकोण के आधार पर निर्भर करते हैं, स्थिरता यह है कि यह वायरल है। जब आप किसी ऑब्जेक्ट का निरंतर संदर्भ देते हैं, तो केवल उन्हीं विधियों को गैर-उत्परिवर्तन के रूप में चिह्नित किया जा सकता है, और आपको संकलक को यह बताना होगा कि विधियों में से कौन सी विधियां हैं। जब आप एक विधि निरंतर घोषित करते हैं, तो आप संकलक को बता रहे हैं कि उस कोड को कॉल करने वाला उपयोगकर्ता कोड ऑब्जेक्ट स्थिति रखेगा। जब आप निरंतर हस्ताक्षर वाले विधि को कार्यान्वित (कार्यान्वित) करते हैं, तो संकलक आपको अपना वादा याद दिलाएगा और वास्तव में यह आवश्यक है कि आप डेटा को आंतरिक रूप से संशोधित न करें।

भाषा आपको अपने तरीकों के कंपाइलर गुणों को बताने में सक्षम बनाती है, जिन्हें आप किसी भी अन्य तरीके से व्यक्त नहीं कर सकते हैं, और साथ ही, संकलक आपको बताएगा कि आप अपने डिज़ाइन का अनुपालन नहीं कर रहे हैं और डेटा को संशोधित करने का प्रयास कर रहे हैं।

इस संदर्भ में, const_cast <> कभी भी उपयोग नहीं किया जाना चाहिए, क्योंकि परिणाम आपको अपरिभाषित व्यवहार के क्षेत्र में ले जा सकते हैं (दोनों भाषा के दृष्टिकोण से: वस्तु केवल पढ़ने-योग्य स्मृति में हो सकती है, और एक से कार्यक्रम बिंदु: आप अन्य वर्गों में invariants तोड़ सकते हैं)। लेकिन, ज़ाहिर है, आप पहले ही जानते हैं कि क्या आप सी ++ एफएक्यू लाइट पढ़ते हैं।

एक साइड नोट के रूप में, जब आप संदर्भों (सी ++ संदर्भ या पॉइंटर्स में) से निपट रहे हैं तो जावा में अंतिम कीवर्ड वास्तव में सी ++ में कॉन्स्ट कीवर्ड से कोई लेना देना नहीं है।अंतिम कीवर्ड स्थानीय चर को संशोधित करता है जिसमें यह संदर्भित करता है, चाहे मूल प्रकार या संदर्भ हो, लेकिन निर्दिष्ट ऑब्जेक्ट का संशोधक नहीं है। यही है, आप अंतिम संदर्भ के माध्यम से उत्परिवर्तन विधियों को कॉल कर सकते हैं और इस प्रकार संदर्भित वस्तु की स्थिति में परिवर्तन प्रदान कर सकते हैं। सी ++ में, संदर्भ हमेशा स्थिर होते हैं (आप केवल उन्हें निर्माण के दौरान किसी ऑब्जेक्ट/चर के साथ बाध्य कर सकते हैं) और कॉन्स कीवर्ड संशोधित करता है कि उपयोगकर्ता कोड निर्दिष्ट ऑब्जेक्ट से कैसे निपट सकता है। (संकेत के मामले में, तुम दोनों गृहीत और सूचक के लिए स्थिरांक कीवर्ड का उपयोग कर सकते हैं: एक्स स्थिरांक * स्थिरांक एक निरंतर एक्स करने के लिए एक निरंतर सूचक वाणी)

+0

धन्यवाद। जैसा कि आप कहते हैं, मैं नहीं करता, ऐसी भाषा से आती है जिसमें स्थिरता नहीं है; सी ++ मेरी सबसे परिचित भाषा है। मैंने अभी कहीं और देखा है, और सोच रहा है कि क्यों सी ++ इस तरह से डिजाइन किया गया है। मुझे अभी भी लगता है कि इंटरफेस को परिभाषित करना एक क्लीनर, कॉन्स कीवर्ड की तुलना में किसी भी प्रकार के एक्सेस प्रतिबंधों को व्यक्त करने का एक सामान्य, अधिक सामान्य तरीका है, जो इसे छूने वाली हर चीज में फैलता है और संदर्भ के आधार पर कई अलग-अलग अर्थ हैं। – Asik

+3

मैं टिप्पणी पर आपसे सहमत नहीं हो सकता। सबसे पहले, यदि आपने कॉन्स के समतुल्य इंटरफेस को परिभाषित किया है, तो आप एक ही परिणाम प्राप्त करने के लिए बहुत से इंटरफ़ेस (और वर्चुअल विधियों) को क्रैम करेंगे, और नतीजा उतना ही वायरल होगा जितना कि कॉन्स कीवर्ड है। कॉन्स्ट कीवर्ड एक्सेस प्रतिबंध के कारण सबकुछ फैलता है क्योंकि यह 'जादू' कीवर्ड होने के कारण नहीं लगाता है। तब मैं वास्तव में आपका अंतिम बिंदु नहीं देखता हूं: '[const] के संदर्भ के आधार पर कई अलग-अलग अर्थ हैं। कॉन्स के लिए केवल एक ही अर्थ है, या क्या मुझे कुछ याद आ रही है? –

4

आप में डेटा के साथ एम्बेडेड उपकरणों के लिए कार्यक्रम लिख रहे हैं, तो फ्लैश या रॉम आप बिना किसी शुद्धता के जी सकते हैं। यह आपको विभिन्न प्रकार की मेमोरी में डेटा के सही हैंडलिंग को नियंत्रित करने की शक्ति देता है।

void const_print(const char* str) 
{ 
    cout << str << endl; 
} 

एक अन्य विधि

void print(char* str) 
{ 
    cout << str << endl; 
} 

मुख्य में:

0

उदाहरण के लिए यदि आप एक funcion है

int main(int argc, char **argv) 
{ 
    const_print("Hello"); 
    print("Hello");  // syntax error 
} 

इसका कारण यह है "हैलो" एक स्थिरांक चार सूचक है, (सी-शैली) स्ट्रिंग केवल स्मृति में पढ़ा जाता है। लेकिन यह तब उपयोगी होता है जब प्रोग्रामर जानता है कि मान नहीं बदला जाएगा। इसलिए सेगमेंटेशन गलती के बजाय कंपाइलर त्रुटि प्राप्त करने के लिए। गैर चाहता था कार्य में तरह:

const int a; 
int b; 
if(a=b) {;} //for mistake 

बाईं संकार्य के बाद से एक स्थिरांक पूर्णांक है।

+0

एक दुर्भाग्यपूर्ण तरफ: पीछे की संगतता कारणों के लिए, एक (बहिष्कृत) छिद्र है कि एक स्ट्रिंग अक्षर को 'char *' में पारित किया जा सकता है, इसलिए आपकी वाक्यविन्यास त्रुटि वास्तव में नहीं है। – Hurkyl

2

एंडर्स हेजल्सबर्ग (सी # आर्किटेक्ट): ... यदि आप एक ऐसी विधि घोषित करते हैं जो गैर-कॉन्स ब्लैस लेता है, तो आप इसे एक कॉन्स ब्लै पास नहीं कर सकते हैं। तो अब आप अटक गए हैं। तो आपको धीरे-धीरे सबकुछ का एक कॉन्स संस्करण चाहिए जो कि नहीं है, और आप एक छाया दुनिया के साथ खत्म हो जाते हैं।

तो फिर: यदि आपने कुछ तरीकों के लिए "कॉन्स्ट" का उपयोग करना शुरू किया है तो आपको आमतौर पर इसे अपने अधिकांश कोड में उपयोग करने के लिए मजबूर होना पड़ता है। लेकिन कोड में कॉन्स-शुद्धता के रखरखाव (टाइपिंग, कुछ कॉन्स गायब होने पर पुन: संकलित करने के लिए खर्च किया गया समय) संभवतः कॉन्स-शुद्धता का उपयोग न करने के कारण संभावित (बहुत दुर्लभ) समस्याओं को ठीक करने के लिए अधिक लगता है। इस प्रकार आधुनिक भाषाओं (जैसे जावा, सी #, गो, इत्यादि) में कॉन्स-इफेक्टनेस सपोर्ट की कमी के परिणामस्वरूप कोड कोड की गुणवत्ता के लिए थोड़ा सा विकास हो सकता है।

स्थिरांक शुद्धता को लागू करने के लिए एक वृद्धि अनुरोध टिकट 1999 के बाद से जावा समुदाय प्रक्रिया में ही अस्तित्व में है, लेकिन जैसा कि ऊपर उल्लेख "स्थिरांक प्रदूषण" और भी अनुकूलता कारणों की वजह से 2005 में बंद हो गया: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070

हालांकि सी # भाषा कोई स्थिरांक है शुद्धता का निर्माण लेकिन इसी तरह की सुविधा संभवतः [शुद्ध] और [अपरिवर्तनीय] का उपयोग करके .NET फ्रेमवर्क के लिए "माइक्रोसॉफ्ट कोड संविदा" (पुस्तकालय + स्थिर विश्लेषण उपकरण) में जल्द ही दिखाई देगा गुण: Pure functions in C#

+0

"यदि आप एक ऐसी विधि घोषित करते हैं जो गैर-कॉन्स ब्लैस लेता है, तो आप इसे एक कॉन्स ब्लै पास नहीं कर सकते हैं। तो अब आप अटक गए हैं।" ऐसा कैसे? आपके पास एक वस्तु है जिसे आप बदलना नहीं चाहते हैं। आप इसे एक ऐसे तरीके से क्यों पारित करना चाहते हैं जिसके हस्ताक्षर के हिस्से के रूप में संभावना है कि इससे कुछ भी बदलेगा? असल में, क्या आप 'कॉन्स int FOO = 42;' घोषित करने में सक्षम होने की उम्मीद करते हैं और फिर 'FOO ++;' करते हैं?'const' बस एक गारंटी है कि कोड एक मूल्य नहीं बदलेगा, और यह संकलक को यह सुनिश्चित करने में आपकी सहायता करने में सक्षम बनाता है कि ऐसा है। मेरे अनुभव में, स्थिरता समग्र विकास के समय को कम कर देता है। –

2

यह talk and videoHerb Sutter वें बताते से थ्रेड-सुरक्षा के संबंध में const का ई नया अर्थ।

Constness कुछ आप के बारे में बहुत ज्यादा से पहले चिंता करने के लिए किया था नहीं हो सकता, लेकिन सी ++ 11 यदि आप धागे की सुरक्षित कोड लिखना चाहते हैं आप const के महत्व और mutable

2
असल

समझने की जरूरत है साथ , यह नहीं है ... वैसे भी, पूरी तरह से नहीं।

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

यह आपको (और आपके कंपाइलर/दुभाषिया) कार्यों के बारे में बेहतर कारण देता है: यदि आप जानते हैं कि एक फ़ंक्शन केवल अपरिवर्तनीय तर्क लेता है, तो आप जानते हैं कि फ़ंक्शन वह नहीं है जो आपके चर को बदल रहा है और एक बग का कारण बन रहा है।

सी और सी ++ कॉन्स का उपयोग करके कुछ ऐसा करते हैं, सिवाय इसके कि यह बहुत कम फर्म गारंटी है: अपरिवर्तनीयता लागू नहीं होती है; कॉल स्टैक के नीचे एक फ़ंक्शन बाध्यता को दूर कर सकता है, और आपके डेटा को बदल सकता है, लेकिन यह एपीआई अनुबंध का जानबूझकर उल्लंघन होगा। तो इरादा या अन्य भाषाओं में अपरिवर्तनीयता की तरह काम करने के लिए सबसे अच्छा अभ्यास है।

जो कुछ भी कहा गया है, सी ++ 11 में अब सीमित सीमित कीवर्ड के साथ वास्तविक म्यूटेबल कीवर्ड है।

+0

'mutable' सी ++ 11 से बहुत पहले आया था, और मुझे यकीन नहीं है कि यह आपके विचार से प्रासंगिक है। इसके अलावा, प्रवर्तन एक चौंकाने वाली चीज़ प्रतीत होता है, क्योंकि सी ++ में काफी कुछ भी सख्ती से लागू नहीं किया जाता है; जैसे अगर मैं 'int x' घोषित करता हूं, तो ऐसा कुछ भी नहीं है जो इस विचार को लागू करता है कि 'x' एक' int 'ऑब्जेक्ट संग्रहीत कर रहा है, क्योंकि मैं इसे भी दूर कर सकता हूं। – Hurkyl

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