2010-10-23 10 views
6

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

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

template <typename T> 
class TEvent { 
    private: T* Owner; 
    public: TEvent(T* parent) : Owner(parent) {} 
}; 

class Foo { 
    private: TEvent<Foo> Froozle; // see below 
}; 

अब समस्या यह है कि मैं Froozle उदाहरण सीधे प्रारंभ नहीं कर सकते, और न ही फू के निर्माता की instanciation सूची का उपयोग कर, क्योंकि this संदर्भ वहाँ की अनुमति नहीं है है। एक और विधि setParent(T*) जोड़ने के अलावा (जो मुझे बहुत पसंद नहीं है क्योंकि इसका मतलब है कि मुझे TEvent<> उदाहरण को अमान्य स्थिति में छोड़ना है), क्या यह हासिल करने का कोई तरीका है?

उत्तर

11

प्रारंभिक सूची में this का उपयोग करना ठीक है, जब तक कि इसका उपयोग किसी भी सदस्य तक पहुंचने के लिए नहीं किया जाता है, जिसे अभी तक प्रारंभ नहीं किया जा सकता है।

+0

वह क्या कहते हैं। जब तक आप जिन वस्तुओं को 'इस' से गुजरते हैं, उन्हें "निर्माण" के दौरान अपने निर्माण के दौरान स्पर्श नहीं किया जाता है (क्योंकि ऑब्जेक्ट 'यह' उस संदर्भ में पूरी तरह से निर्मित नहीं होता है), ऐसा करने से कुछ ठीक है, भले ही कुछ कंपाइलर (विशेष रूप से वीसी) इसके लिए एक चेतावनी उत्सर्जित करें। – sbi

+0

वीसी ++ यहां महत्वपूर्ण बिंदु है। यह वास्तव में काम करता है। ऐसा लगता है कि मुझे जबरन "त्रुटि" दबाना है। आपका बहुत बहुत धन्यवाद! – sunside

+1

मेरी इच्छा है कि वीसी ++ केवल चेतावनी उत्सर्जित करे जब सीटीआर के अंदर "इस" के सदस्य का उपयोग किया जाए। बीटीडब्लू, गूगल :: लॉग-मैसेज क्लास [google-glog] (http://code.google.com/p/google-glog) डीबग उद्देश्य के लिए सीटीआर की मेम-स्टार्टिस्ट सूची में खुद को "यह" स्टोर करता है। मुझे वीसी -2010 में काम करने के लिए #pragma चेतावनी (4355: अक्षम) के साथ पुन: संकलित करना पड़ा। –

1

यह काम करना चाहिए; वास्तव में,

template<class T> 
class Child { 
private: 
    T *parent; 
public: 
    Child(T *parent) : parent(parent) {} 
}; 
class Parent { 
private: 
    Child<Parent> child; 
public: 
    Parent() : child(this) {} 
}; 

दोनों g ++ 4.4.5 और clang ++ 2.8 दोनों के साथ मेरे लिए ठीक संकलित करता है।

आपके लिए क्या असफल रहा है?

+0

'त्रुटियों के रूप में चेतावनियां' वीसी के संकलक ध्वज और एमएसडीएन दस्तावेज शीर्षलेख जो "त्रुटि संदेश" कहता है। :) आप बिल्कुल सही हैं - यह काम करता है, मैंने इसे अभी नहीं देखा। आपका बहुत बहुत धन्यवाद! – sunside

10

मानक 12.6.2/7 "ठिकानों और सदस्यों शुरु कर रहा है" (जोर मेरा) से:

एक मेम-प्रारंभकर्ता की अभिव्यक्ति-सूची में

नाम निर्माता के दायरे में मूल्यांकन किया जाता है जिसके लिए मेम-प्रारंभकर्ता निर्दिष्ट है।

[उदाहरण:

class X { 
    int a; 
    int b; 
    int i; 
    int j; 

public: 
    const int& r; 
    X(int i): r(a), b(i), i(i), j(this->i) {} 
}; 

X::r initializes X::a का उल्लेख करने, निर्माता पैरामीटर i के मूल्य के साथ X::b initializes, initializes निर्माता पैरामीटर i के मूल्य के साथ X::i, और आरंभ X::j X::i के मूल्य के साथ; यह प्रत्येक बार class X की वस्तु उत्पन्न होता है। ]

[नोट: क्योंकि मेम-प्रारंभकर्ता निर्माता के दायरे में मूल्यांकन किया जाता है, this सूचक एक सदस्य-प्रारंभकर्ता जा रहा है वस्तु का उल्लेख करने की अभिव्यक्ति-सूची में इस्तेमाल किया जा सकता प्रारंभ। ]

+1

वह पागल दिखता है। : डी – sunside

+0

क्या इसका मतलब यह है कि "यह" केवल सीटीओआर की याद-प्रारंभकर्ता सूची में ही अनुमति है या क्या इसे सीटीआर के शरीर में भी अनुमति है? मैंने वीसी -2010 ++ में सीटीआर के शरीर के अंदर "यह" का उपयोग करने की कोशिश की है और यह सभी संकलित करता है और चेतावनी C4355 अक्षम के साथ ठीक चलाता है, लेकिन सिर्फ इसलिए कि यह काम करता है इसका मतलब यह नहीं है कि मुझे अनुमति है। अब तक, मुझे [ओपन-स्टैंडर्ड डॉक्टर] में कोई नहीं मिला है (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf) जो बताता है कि यह है या नहीं ctor के शरीर के अंदर "यह" को संदर्भित करने की अनुमति है या नहीं। –

+0

@ डेविड लि: कन्स्ट्रक्टर के अंदर, 'यह' ऑब्जेक्ट का निर्माण करने के लिए इंगित करता है (जैसा कि ऊपर वर्णित आरंभकर्ता सूची में है)। आप निश्चित रूप से कन्स्ट्रक्टर बॉडी के अंदर 'इस' का उपयोग कर सकते हैं। –

1

आप, चेतावनी को दबाने के लिए देख रहे हैं तो बस इस कार्य करें:

class Foo 
{ 
public: 
    Foo() : 
    Froozle(get_this()) 
    {} 

private: 
    Foo* get_this() 
    { 
     return this; 
    } 

    TEvent<Foo> Froozle; // see below 
}; 

अविवेक इसे रोकने के लिए पर्याप्त है।

+0

हे। एक विधि कॉल ठीक क्यों है लेकिन प्रत्यक्ष संदर्भ नहीं है? मूर्खतापूर्ण संकलक :) – ephemient

1

मुझे नहीं लगता कि यह आपके लिए असफल रहा है, जब तक कि आपके पास चेतावनी स्तर 4 पर सेट न हो (या इसी तरह, मैं विजुअल स्टूडियो मानता हूं) और "त्रुटियों के रूप में चेतावनियों का इलाज" सक्षम कर दिया है।

असल में, इस चेतावनी के बाद से यह आप नहीं दूँगी गलती से उपयोगthis सूचक जब क्या यह कम से बताते हैं अभी तक निर्माण किया जा रहा है, एक अच्छी बात है।

हालांकि, जब आप जानते हैं कि आप कहां कर रहे हैं this प्रारंभिक सूची में पारित किया गया है, तो इसके कारण चेतावनी और त्रुटि परेशान होगी।

आप (फिर से, दृश्य स्टूडियो कल्पना करते हुए) सजाने निर्माता द्वारा यह से छुटकारा पा सकते हैं (जब तक यह वर्ग घोषणा में परिभाषित किया है - तो आप सभी वर्ग को सजाने चाहिए):

// warning C4355: 'this' : used in base member initializer list 
#pragma warning (push) 
#pragma warning (disable : 4355) 
some_class::some_class() 
: ... 
{ 
} 
#pragma warning (pop) 
संबंधित मुद्दे