2010-07-07 11 views
29

मेरे पास एक वर्ग है जो इस तरह दिखता है:सी ++: एक सदस्य सूचक को शून्य करने के लिए शुरू करें?

class Foo 
{ 
public: 
    Foo(); 
    virtual ~Foo(); 

private: 
    Odp* bar; 
}; 

मैं bar को NULL में प्रारंभ करना चाहता हूं। क्या यह करने का सबसे अच्छा तरीका है?

Foo::Foo() : bar(NULL) 
{ 
} 

इसके अलावा, क्या यह आवश्यक है कि विनाशक आभासी है? (यदि यह सत्य है, तो कन्स्ट्रक्टर वर्चुअल भी होना चाहिए?)

+1

तर्कसंगत रूप से बेहतर है 'Foo :: Foo(): bar() {} '(नोट, नहीं' NULL'।) सबसे अच्छा पॉइंटर नहीं है, हालांकि। – GManNickG

+2

यह बेहतर क्यों है? क्या 'नूल' अंतर्निहित है? –

+2

"यह बेहतर क्यों है?" आपको 'NULL' की परिभाषा के लिए हेडर फ़ाइल शामिल करने की आवश्यकता नहीं है (जो कि वैसे भी' 0' है)। "क्या 'पूर्ण' अंतर्निहित है?" हाँ। 'बार()' मूल्य-प्रारंभिकता है; एक सूचक के मामले में, यह इसे शून्य करने के लिए शुरू होता है। –

उत्तर

39

मैं NULL को bar प्रारंभ करना चाहते हैं। क्या यह करने का सबसे अच्छा तरीका है?

यह सही तरीका है। तो हाँ।

साथ ही, यह आवश्यक है कि विनाशक आभासी हो?

सं नाशक केवल आप Foo वर्ग से इनहेरिट किया जाएगा यदि और (हालांकि अंगूठे का एक सामान्य नियम के रूप में उन व्युत्पन्न वर्ग को हटाने के लिए एक Foo सूचक का उपयोग किया जाएगा आभासी होने की जरूरत है, यह अगर आभासी होना चाहिए कोई अन्य आभासी सदस्य हैं)।

(यदि यह सच है, तो निर्माता आभासी रूप में अच्छी तरह होना चाहिए?)

सं कंस्ट्रक्टर्स न जरूरतvirtual हो सकता है, और न ही कर सकते हैं वे।

+0

+1 अच्छा संक्षिप्त उत्तर। मैं ctor के शरीर में गैर निरंतर सदस्यों को शुरू करता हूं। यह कोड को थोड़ा और स्पष्ट (सदस्य क्वालीफायर के प्रकार के संबंध में) पढ़ता है। – Poni

+14

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

+0

MyClass :: MyClass(): m_const_var (VALUE) {this-> m_non_const_var = OTHER_VALUE} <<<< जीएमएन ने जो कहा वह बिल्कुल ठीक नहीं हुआ लेकिन मेरा यही मतलब था।तो, आप कह रहे हैं कि यह तरीका गलत है? आप कह रहे हैं कि हमें m_con_const_var के प्रारंभ में ctor के सदस्यों के प्रारंभिक क्षेत्र में m_const_var के साथ करना चाहिए? – Poni

10
  1. हां, प्रारंभकर्ता सूची सर्वोत्तम है।

  2. शायद। यदि आप वर्ग में कोई अन्य आभासी कार्य करना चाहते हैं, या यदि आप कक्षा को विरासत में प्राप्त करना चाहते हैं तो विनाशक आभासी होना चाहिए (हालांकि आम तौर पर उन चीजों को एक साथ जाना जाता है)।

  3. नहीं। C++ में वर्चुअल कन्स्ट्रक्टर होना संभव नहीं है। (क्या ऐसी बात भी मतलब होगा?)

अपने प्रश्न की प्रकृति मेरे लिए पता चलता है क्या तुम सच में समझ में नहीं आता कि क्या virtual कीवर्ड करता है, या क्या है के लिए है, और आप अभी कर रहे हैं आप कहीं और या ट्यूटोरियल में देखा कुछ कॉपी। आपके द्वारा लिखे गए कोड के सभी के उद्देश्य को समझना सर्वोत्तम है। http://www.parashift.com/c++-faq-lite/virtual-functions.html

+0

"इस तरह की चीज़ का क्या मतलब होगा?" के जवाब में बस एक एफवाईआई: कुछ लोग फैक्ट्री पैटर्न (http://www2.research.att.com/~bs/bs_faq2) के लिए "आभासी कन्स्ट्रक्टर" शब्द का उपयोग कर सकते हैं। एचटीएमएल # आभासी-ctor)। लिंक के लिए –

+0

+1। यह बहुत उपयोगी है। –

2

1 हां

2,, केवल यदि आप किसी को अपने वर्ग से प्राप्त करने और आधार वर्ग के लिए एक सूचक का उपयोग सक्षम होना चाहते हैं - लेकिन बनाने dtor आभासी वैसे भी: यहाँ शुरू करने के लिए एक जगह हो सकता है

3, कोई आप एक आभासी ctor हो सकता है नहीं (या सभी ctors आभासी मुझे लगता है कर रहे हैं?)

+4

"सभी सीटीआर आभासी हैं" - नहीं, जिस पर संकलक कॉल करने के लिए संकलन समय पर किया जाता है। "आभासी" एक रन-टाइम निर्णय का संकेत देगा। –

4
  1. हाँ
  2. के बारे में नाशक जा रहा है आभासी देखने आपके दूसरे प्रश्न के बारे में: http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.7 कम जवाब है, नहीं नाशक अपने मामले में vitual होने के लिए आवश्यक नहीं है।
  3. वर्चुअल कन्स्ट्रक्टर जैसी कोई चीज नहीं है।
3

एक अन्य विकल्प आप विचार करना चाह सकते एक कच्चे सूचक के बजाय एक स्मार्ट सूचक वर्ग (जैसे boost::scoped_ptr, boost::shared_ptr या C++ 0x के unique_ptr) का प्रयोग है। स्मार्ट पॉइंटर का कन्स्ट्रक्टर यह सुनिश्चित करेगा कि अगर आपको कुछ अन्य स्पष्ट प्रारंभिकरण की आवश्यकता नहीं है तो यह कुछ नल की तरह शुरू हो जाएगा। स्मार्ट पॉइंटर यह भी सुनिश्चित करेगा कि ऑब्जेक्ट-ऑब्जेक्ट नष्ट हो गया है।

तुम बस तय करने के लिए क्या स्मार्ट बिंदु नीति की तरह आइटम के लिए उपयुक्त है और तदनुसार (यहां तक ​​कि auto_ptr एक कच्चे सूचक की तुलना में बेहतर रूप में लंबे समय के रूप में आप विभिन्न कमियों के बारे में पता कर रहे हैं हो सकता है) की जरूरत है।

9

चार अलग-अलग तरीके मौजूद हैं। कौन सा सबसे अच्छा है करने के लिए आप

Foo::Foo() : bar() // value initialization 
{ 
} 

Foo::Foo() : bar(0) // direct null pointer constant 
{ 
} 

Foo::Foo() : bar(NULL) // null pointer constant by macro 
{ 
} 

Foo::Foo() : bar(nullptr) // pointer literal of type std::nullptr_t 
{ 
} 
+0

और अब 'Foo :: Foo(): बार (nullptr) {} ' – nurettin

0

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

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