क्यों स्पष्ट रूप से निर्माता को हटा दें?


93

कब / क्यों मैं स्पष्ट रूप से अपने निर्माता को हटाना चाहूंगा? यह मानते हुए कि इसके उपयोग को रोकने के लिए, बस इसे क्यों नहीं बनाया जाए private?

class Foo
{ 
  public: 
    Foo() = delete; 
};

14
यह अच्छी तरह से चला जाता है = default, यहां तक ​​कि वर्ग भी इसका उपयोग नहीं कर सकता है, और मैं व्यक्तिगत रूप से हटाए गए फ़ंक्शन का उपयोग देखना पसंद करता हूं ओवर फंक्शन निजी है। पूर्व में स्पष्ट रूप से कहा गया है "यह उपयोग करने के लिए नहीं है।" अगर इससे कुछ भी निकलता है, तो इसका उपयोग नहीं करने वाला वर्ग वास्तव में एक शब्दार्थिक अंतर बनाता है।
च्रिस

15
मुझे ईमानदारी से लगता है कि लोग करीबी वोटों के साथ आक्रामक होने लगे हैं। मैं यह नहीं देखता कि यह रचनात्मक कैसे नहीं है।
लुचियन ग्रिगोर

4
@LuchianGrigore: सहमत। मैं सोच रहा था कि समुदाय अपने आप में इतना कठोर क्यों हो गया है। मैं बात नहीं देख रहा हूँ।
एड एस।

11
चूँकि मैं शायद ही कभी C ++ 11 का उपयोग करता हूं, इसलिए यह मेरे लिए अधिक जानकारीपूर्ण है कि शायद ओपी को भी पता चल गया है। मुझे यह भी नहीं पता था कि आप एक कंस्ट्रक्टर को टैग कर सकते हैंdelete । प्रश्न और लुचियन दोनों का उत्तर आसानी से रचनात्मक के रूप में योग्य है। कोई भी C ++ 11 के महीन बिंदुओं पर सांस नहीं ले रहा है, लेकिन जल्द ही दोनों में से कुछ पाने की जरूरत होगी।
WhozCraig

जवाबों:


87

कैसा रहेगा:

//deleted constructor
class Foo
{ 
  public: 
    Foo() = delete;     
  public:
    static void foo();
};

void Foo::foo()
{
   Foo f;    //illegal
}

बनाम

//private constructor
class Foo
{ 
  private: 
    Foo() {}     
  public:
    static void foo();
};

void Foo::foo()
{
   Foo f;    //legal
}

वे मूल रूप से अलग चीजें हैं। privateआपको बताता है कि केवल कक्षा के सदस्य ही उस पद्धति को कह सकते हैं या उस चर (या पाठ्यक्रम के मित्र) तक पहुंच सकते हैं। इस मामले में, यह staticउस वर्ग (या किसी अन्य सदस्य) की एक विधि के लिए एक वर्ग के privateनिर्माता को कॉल करने के लिए कानूनी है । यह हटाए गए निर्माणकर्ताओं के लिए नहीं है।

यहाँ नमूना ।


3
यदि आप फू (इंट) की घोषणा करते हैं, तो आपको फू () की घोषणा करने की आवश्यकता नहीं है। फू () उत्पन्न नहीं किया जाएगा और इस प्रकार फू च अमान्य है। तो आपका उदाहरण हटाए गए कंस्ट्रक्टर के लिए मामला नहीं दिखाता है। अपने लिए देखें - ideone.com/mogiIF
अंक

1
@मार्क मैंने बात साबित करने के लिए 2 कंस्ट्रक्टर लिखे। मैं संपादित करूँगा इसलिए यह सभी के लिए स्पष्ट है।
लुचियन ग्रिगोर

1
मुझे अंतर समझ में आता है, मैं अभी डिलीट स्टेटमेंट के अतिरिक्त मूल्य को सामान्य रूप से और विशेष रूप से एक कंस्ट्रक्टर के लिए नहीं समझता। आखिरकार, मैं शरीर के बिना एक निजी डिफ़ॉल्ट कंस्ट्रक्टर निर्दिष्ट कर सकता हूं। फिर लिंक के दौरान भी कोड विफल हो जाता है। ठीक है, मैं देख सकता हूं कि डिलीट का इरादा और अधिक स्पष्ट रूप से व्यक्त करता है, लेकिन यह इसके बारे में है।
अंक

11
@मार्क हां, यह चीजों को करने का C ++ 98 तरीका होगा। लेकिन IMHO, इरादे को स्पष्ट रूप से व्यक्त करना वास्तव में सामान्य रूप से प्रोग्रामिंग में एक बहुत महत्वपूर्ण बात है। इस मामले में, कुछ पाठक एक निजी अपरिभाषित कंस्ट्रक्टर को देख सकते हैं और मान सकते हैं कि यह आकस्मिक है और इसके लिए केवल एक परिभाषा जोड़ें, खासकर अगर परिभाषा एक डिफ़ॉल्ट कंस्ट्रक्टर के रूप में तुच्छ है (हाँ, एक टिप्पणी होने से मदद मिलती है, लेकिन हम बहुत संकलक होंगे (टिप्पणी-प्रवर्तन पर प्रवर्तन)। हमारे इरादे स्पष्ट होने से, हमें एक बेहतर त्रुटि संदेश भी मिलता है जो "अपरिभाषित संदर्भ" के बजाय "स्पष्ट रूप से हटा दिया गया" कहता है।
मप्र

2
मैं ईमानदारी से नहीं समझता कि यह मुख्य प्रश्न का उत्तर कैसे देता है। शीर्षक में प्रश्न और पोस्ट में ओपी का पहला सवाल था: मैं / मेरे निर्माता को स्पष्ट रूप से क्यों / कब हटाना चाहते हैं?
अलेक्जेंडर बोलिन्स्की

11

क्यों स्पष्ट रूप से निर्माता को हटा दें?

एक और कारण:
मैं उपयोग deleteकरता हूं जब मैं यह आश्वासन देना चाहता हूं कि एक वर्ग को एक इनिशलाइज़र के साथ कहा जाता है। मैं इसे बिना रनटाइम जाँच के प्राप्त करने के लिए एक बहुत ही सुंदर तरीका मानता हूं।

C ++ कंपाइलर आपके लिए यह जांच करता है।

class Foo
{
   public:
       Foo() = delete;
       Foo(int bar) : m_bar(bar) {};
   private:
       int m_bar;
}

यह - बहुत सरलीकृत - कोड आश्वासन देता है कि इस तरह कोई तात्कालिकता नहीं है:Foo foo;


12
हटाए गए घोषणा पत्र यहां अनावश्यक है। यह किसी भी उपयोगकर्ता द्वारा प्रदान किए गए निर्माता के साथ स्वचालित रूप से हटा दिया गया है
माइक

5
@MikeLui द्वारा टिप्पणी को स्पष्ट करने के लिए, हटाए गए घोषणा संकलक के लिए अनावश्यक है । ऐसे कई मामले हैं जब इस तरह के कोड को अन्य प्रोग्रामर के इरादे की घोषणा करने के लिए शामिल किया जाना चाहिए ।
जेफ जी

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

मुझे अभी भी पता नहीं है कि कंस्ट्रक्टर विच की घोषणा के साथ अतिरिक्त लाइन "= डिलीट" कीवर्ड "नो डिफॉल्ट कंस्ट्रक्टर" विचार के इरादे से बेहतर घोषित करता है ... बस कोई डिफॉल्ट कंस्ट्रक्टर नहीं है? नमूना: मैं अपने कोड में वेरिएबल को "ए" घोषित नहीं करना चाहता हूं - क्या बेहतर है, लिखने के लिए "// int a? // वेरिएबल को परिभाषित करने की आवश्यकता नहीं है" या कोड में इस वेरिएबल के बारे में कुछ भी नहीं लिखना है?
Ezh

2

मैं एलएलवीएम के स्रोत कोड (उदाहरण के लिए AlignOf.h) में 'हटाए गए' के ​​रूप में घोषित डिफ़ॉल्ट ctors के साथ मिला हूं। संबद्ध वर्ग टेम्पलेट आमतौर पर एक विशेष नामस्थान में होते हैं, जिन्हें 'llvm :: detail' कहा जाता है। मुझे लगता है कि पूरा उद्देश्य यह था कि वे उस वर्ग को केवल सहायक वर्ग मानते थे। उन्होंने कभी भी उन्हें पलटने का इरादा नहीं किया; केवल कुछ मेटाप्रोग्रामिंग ट्रिक्स के साथ अन्य क्लास टेम्प्लेट के संदर्भ में उनका उपयोग करने के लिए जो संकलन समय में चलते हैं।

उदाहरण के लिए। यह AlignmentCalcImpl वर्ग टेम्पलेट है जो केवल एक अन्य वर्ग टेम्पलेट के भीतर उपयोग किया जाता है जिसे AlignOf कहा जाता है जो आकार (।) ऑपरेटर के लिए एक पैरामीटर है। संकलन समय में उस अभिव्यक्ति का मूल्यांकन किया जा सकता है; और टेम्पलेट को तत्काल करने की कोई आवश्यकता नहीं है -> तो इस इरादे को व्यक्त करने के लिए डिफ़ॉल्ट ctor को हटाएं क्यों नहीं।

लेकिन यह केवल मेरी धारणा है।

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