2012-05-31 14 views
14

एक वास्तविक समस्या का एक सरलीकृत संस्करण निम्नलिखित है। Base::operator=(int) पर कॉल करने के बजाय, कोड अस्थायी Derived ऑब्जेक्ट उत्पन्न करने के लिए प्रतीत होता है और इसकी बजाय प्रतिलिपि बनाता है। बेस असाइनमेंट ऑपरेटर का उपयोग क्यों नहीं किया जाता है, क्योंकि फ़ंक्शन हस्ताक्षर पूरी तरह से मेल खाता है? यह सरलीकृत उदाहरण किसी भी बीमार प्रभाव को प्रदर्शित नहीं करता है, लेकिन मूल कोड के विनाशक में दुष्प्रभाव होता है जो सभी प्रकार के विनाश का कारण बनता है।व्युत्पन्न कक्षा बेस क्लास ऑपरेटर = (असाइनमेंट ऑपरेटर) का उपयोग क्यों नहीं करती है?

#include <iostream> 
using namespace std; 

class Base 
{ 
public: 
    Base() 
    { 
     cout << "Base()\n"; 
    } 

    Base(int) 
    { 
     cout << "Base(int)\n"; 
    } 

    ~Base() 
    { 
     cout << "~Base()\n"; 
    } 

    Base& operator=(int) 
    { 
     cout << "Base::operator=(int)\n"; 
     return *this; 
    } 
}; 

class Derived : public Base 
{ 
public: 
    Derived() 
    { 
     cout << "Derived()\n"; 
    } 

    explicit Derived(int n) : Base(n) 
    { 
     cout << "Derived(int)\n"; 
    } 

    ~Derived() 
    { 
     cout << "~Derived()\n"; 
    } 
}; 

class Holder 
{ 
public: 
    Holder(int n) 
    { 
     member = n; 
    } 

    Derived member; 
}; 

int main(int argc, char* argv[]) 
{ 
    cout << "Start\n"; 
    Holder obj(1); 
    cout << "Finish\n"; 

    return 0; 
} 

उत्पादन होता है:

Start 
Base() 
Derived() 
Base(int) 
Derived(int) 
~Derived() 
~Base() 
Finish 
~Derived() 
~Base() 

http://ideone.com/TAR2S

उत्तर

19

यह एक संकलक उत्पन्न operator= विधि और member function hiding के बीच एक सूक्ष्म बातचीत है। चूंकि व्युत्पन्न वर्ग ने किसी भी ऑपरेटर = सदस्यों की घोषणा नहीं की है, इसलिए एक को संकलक द्वारा स्पष्ट रूप से उत्पन्न किया गया था: Derived& operator=(const Derived& source)। यह ऑपरेटर = बेस क्लास में ऑपरेटर = छुपाया गया ताकि इसका उपयोग नहीं किया जा सके। संकलक अभी भी Derived(int) कन्स्ट्रक्टर का उपयोग करके एक अस्थायी वस्तु बनाकर असाइनमेंट को पूरा करने में सक्षम था और इसे पूर्ण रूप से जेनरेट किए गए असाइनमेंट ऑपरेटर के साथ कॉपी करें।

क्योंकि छिपाने वाले कार्य को पूरी तरह से उत्पन्न किया गया था और स्रोत का हिस्सा नहीं था, यह स्पॉट करना बहुत मुश्किल था।

explicit कीवर्ड int कन्स्ट्रक्टर पर कीवर्ड का उपयोग करके खोजा जा सकता था - कंपाइलर स्वचालित रूप से अस्थायी ऑब्जेक्ट उत्पन्न करने के बजाय एक त्रुटि जारी करता। मूल कोड में अंतर्निहित रूपांतरण एक अच्छी तरह से उपयोग की जाने वाली सुविधा है, इसलिए explicit का उपयोग नहीं किया गया था।

समाधान काफी सरल है, व्युत्पन्न वर्ग स्पष्ट रूप से बेस क्लास से परिभाषा खींच कर सकते हैं:

using Base::operator=; 

http://ideone.com/6nWmx

+0

यह जानना अच्छा है! मुझे लगता है कि 'ऑपरेटर =' एकमात्र ऐसा है जो इस व्यवहार को प्रदर्शित करता है (रचनाकारों के लिए समझ में नहीं आता है और कोई अन्य कंपाइलर-जेनरेटेड विधियां नहीं हैं)। –

+0

@ लचियनग्रिगोर, मुझे उम्मीद है! इसने हमें सभी प्रकार के सिर खरोंच के कारण बनाया, मैं फिर से इसमें भागना नहीं चाहता। –

+0

एक-तर्क (सक्षम) रचनाकार लगभग हमेशा आपको 'स्पष्ट' टाइप करना चाहिए। –

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