2013-09-06 7 views
5

का अजीब व्यवहार मैं इस कोड का परीक्षण कर रहा हूं और सोच रहा हूं कि संकलन समय में यह क्यों विफल नहीं हुआ? मैं सी ++ 11 और जी ++ 4.7.2 का उपयोग कर रहा हूं।सी ++ कन्स्ट्रक्टर

मेरे उत्पादन कोड पर समान संरचना थी, यह रन टाइम पर त्रुटियां दे रहा था, फिर मैंने पाया कि मैं गलत तर्क प्रकार के साथ कक्षा का निर्माण कर रहा हूं। ताकि आप Work निर्माता के लिए एक Word पारित कर सकते हैं

#include <iostream> 
#include <vector> 


typedef std::vector<std::string> Word; 

class Data { 
    public: 
     const Word &word; 
     Data(Word w) : word(w) {} 
}; 

class Base{ 
    const Data &data; 
    public: 
     Base(const Data &d): data(d) {} 
     ~Base() {} 
}; 

class Work : public Base{ 
    public: 
     Work(const Data &d): Base(d){} 
     ~Work() {} 
}; 


int main(int argc, char **argv){ 
    Word words; 
    words.push_back("work"); 

    /* 
    * I'm confused with this constructor, why this passed the compilation 
    * ?? 
    * Any special rule to reason this scenario ?? 
    * 
    * But obviously it will fail at run time. 
    */ 
    const Work *work = new Work(words); 

    return 0; 
} 
+1

शायद कहीं एक निहित रूपांतरण चल रहा है? –

+0

शब्द डेटा कन्स्ट्रक्टर द्वारा डेटा में कनवर्ट किए जाते हैं और फिर कार्य (डेटा) – ZijingWu

+0

पर कॉल क्यों विफल हो जाते हैं? Http://ideone.com/cxkf4X पर यह सफलता देता है। – xanatos

उत्तर

10

Data, Word से constructible है। हुड के तहत, Data का एक उदाहरण उत्तीर्ण Word से बनाया जाएगा और बदले में, निर्माता को पास कर दिया जाएगा।

आप Data के निर्माता है कि एक Wordexplicit के रूप में इस तरह लेता है, चिह्नित करके इससे बचने कर सकते हैं: Work निर्माता को

class Data { 
    public: 
     const Word &word; 
     explicit Data(Word w) : word(w) {} 
}; 

इस तरह, निर्माता परोक्ष अब और लागू नहीं किया जा सकता है और अपने कॉल करेंगे संकलित करने के लिए असफल जब तक आप स्पष्ट Data निर्माता आह्वान:

const Work *work = new Work(words);  // Implicit call, fails to compile. 
const Work *work = new Work(Data(words)); // Explicit call, compiles. 
+1

बेशक, 'डेटा' का कन्स्ट्रक्टर काम नहीं करेगा, क्योंकि यह तर्क के संदर्भ को बांधता है, जो कि कन्स्ट्रक्टर लौटने पर नष्ट हो जाएगा। –

+1

@ एमएम।, हाँ, यह है। 'मुख्य' 'के लिए स्थानीय' शब्द 'महत्वपूर्ण नहीं हैं क्योंकि' कार्य 'का उदाहरण' मुख्य() 'के लिए भी स्थानीय है, लेकिन 'वर्क' कन्स्ट्रक्टर अस्थायी 'डेटा' उदाहरण के लिए है, जैसा कि जेम्स पॉइंट्स बाहर, और यह वास्तव में बुरी खबर है। –

+1

अब मुझे समझ में आया कि मेरा प्रोग्राम रन टाइम के दौरान segfault क्यों देता है (खतरनाक संदर्भ तक पहुंचने पर क्रैश)। –

5

यह काम करता है सह mpiles * क्योंकि Data एक अंतर्निहित रूपांतरण निर्माता है कि एक Word संदर्भ लेता है:

Data(Word w) : word(w) {} 

इसका मतलब है आप इस तरह के

Word words; 
Data d1 = words; 
Data d2(words); 

के रूप में काम कर सकते हैं और आप निर्माता के माध्यम से एक Data से एक Work निर्माण कर सकते हैं Work(const Data &d): Base(d){}:

Work w(d2); 

जो निम्नलिखित का मतलब है, यह भी मान्य है, क्योंकि यह केवल एक उपयोगकर्ता-निर्धारित रूपांतरण शामिल है:

Work w2(words); // constructs Data temporary from words, then constructs w2 with it 

यह व्यवहार explicit के रूप में परिवर्तित करने के निर्माता की घोषणा के द्वारा दबा दिया जा सकता है:

explicit Data(Word w) : word(w) {} 

* आपका नहीं करता है वास्तव में काम नहीं करते क्योंकि इसमें अस्थायी Data ऑब्जेक्ट

+0

प्रश्न के अलावा, क्या यह 'डेटा' कक्षा में खतरनाक संदर्भ के कारण एक अनिर्धारित व्यवहार नहीं है? 'शब्द' एक अस्थायी वस्तु को संदर्भित करता है। – deepmax

+0

@ एमएम। मैं बस इसके बारे में एक नोट जोड़ रहा था :) – juanchopanza

2

निम्न कन्स्ट्रक्टर से बाहर निकलने के बाद एक हानिकारक संदर्भ शामिल है, डेटा

class Data { 
    public: 
     const Word &word; 
     Data(Word w) : word(w) {} 
}; 

स्वत: भंडारण अवधि का एक चर w रखने के लिए बनाया गया है: संदर्भ प्रकार के सदस्य word एक वस्तु है कि अब मौजूद नहीं है को संदर्भित कर दिया जाएगा। आप उस चर के संदर्भ को सदस्य word के रूप में संग्रहीत करते हैं, फिर रेफरी कन्स्ट्रक्टर के बाहर निकलने पर नष्ट हो जाती है।

अन्य समस्याओं के बावजूद, मुझे नहीं लगता कि यह आपका इरादा है।

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