2015-06-24 19 views
5

में सी ++ असाइनमेंट ऑपरेटर मुझे समझ में नहीं आता है कि एक व्युत्पन्न कक्षा के लिए क्यों बेस क्लास के संबंधित ऑपरेटर को कॉल नहीं किया जाता है, यदि इसका अस्तित्व मौजूद नहीं है। कोड को देखें:व्युत्पन्न वर्ग

#include <iostream> 
using namespace std; 

class A{ 
protected: 
    void myWrite(){ 
    cout << " Base " <<endl; 
    } 
public: 
    double x,y; 
    A(): x{0},y{0}{}; 
    virtual A & operator=(double g){x=g;y=g;return *this;} 
    virtual ~A(){}; 
    virtual void doneit(){myWrite();} 
}; 


class B: public A{ 
protected: 
public: 
    B():A(){}; 
    virtual ~B(){}; 
    virtual void doneit(){myWrite();} 
}; 

int main() { 
    A jj; 
    B pp; 

    pp=0.0; 
    return 0; 
} 

चूंकि यह कोड संकलित नहीं होता है। बेशक अगर मैं ए के लिए समान के लिए "ऑपरेटर =" परिभाषित करता हूं, तो सबकुछ काम करता है, लेकिन बी "ऑपरेटर =" को डिफ़ॉल्ट रूप से क्यों नहीं कहा जाता है यदि व्युत्पन्न वर्ग में से कोई परिभाषित नहीं किया गया है ?? क्या आप इस मुद्दे पर कुछ प्रकाश डालने में मदद कर सकते हैं?

जीसीसी कंपाइलर कहता है ../src/tito.cpp:40hold: त्रुटि: कोई व्यवहार्य ओवरलोडेड '=' पीपी = 0.0; ~~^~~~ ../src/tito.cpp:28:7: नोट: उम्मीदवार फ़ंक्शन (निहित प्रति असाइनमेंट ऑपरेटर) व्यवहार्य नहीं है: 1 तर्क के लिए 'डबल' से 'कॉन्स्ट बी' से कोई ज्ञात रूपांतरण नहीं कक्षा बी: सार्वजनिक ए { ^ 1 त्रुटि उत्पन्न हुई।

क्या आप समझा सकते हैं कि यह क्यों काम नहीं करता है?

उत्तर

8

यदि आप प्रतिलिपि असाइनमेंट ऑपरेटर घोषित नहीं करते हैं, तो संकलक आपके लिए एक घोषित करेगा। तो अपने वर्ग Bवास्तव में लगता है:

class B : public A { 
public: 
    // explicit 
    B(); 
    virtual ~B(); 
    virtual void doneit(); 

    // implicit 
    B(const B&); 
    B& operator=(const B&); 
}; 

निहित प्रति असाइनमेंट ऑपरेटर खालA::operator=(double) है कि आप ने लिखा है, तो यह केवल उम्मीदवार उस नाम देखने को ढूंढेगा। बेशक, यह व्यवहार्य उम्मीदवार नहीं है, क्योंकि double परिवर्तनीय नहीं है B, इसलिए त्रुटि।

A::operator=(double) ऑपरेटर का उपयोग करने के लिए, आप स्पष्ट रूप से दायरे में लाना होगा:

using A::operator=; 

लेकिन तब आप B भाग के किसी भी बताए जा करने के लिए नहीं जा रहे हैं। तो यह अधिक स्पष्ट होने के लिए बेहतर होगा:

B& operator=(double g) { 
    // B stuff here 

    // A stuff 
    A::operator=(g); 

    return *this; 
} 
+1

है हाँ, मुख्य तर्क यह है कि माता-पिता की 'ऑपरेटर है =' तो परोक्ष बच्चे के हिस्सा आवंटित नहीं है कि यह easilly टूटी हुई वस्तुओं बना सकते हैं का उपयोग कर। – StenSoft

+0

बहुत उपयोगी टिप्पणी के लिए धन्यवाद !! – Max

2

व्युत्पन्न वर्ग है कि परोक्ष संकलक द्वारा घोषित की प्रति असाइनमेंट ऑपरेटर आधार वर्ग का काम ऑपरेटरों छुपाता है। व्युत्पन्न वर्ग में घोषणा का उपयोग कर निम्नलिखित तरीके

class B: public A{ 
protected: 
public: 
    using A::operator =;  
    B():A(){}; 
    virtual ~B(){}; 
    virtual void doneit(){myWrite();} 
}; 

एक और दृष्टिकोण है व्युत्पन्न वर्ग

B & operator=(double g) { A::operator =(g) ;return *this;} 

इस मामले आप बहुरूपता का उपयोग कर सकते में आभासी असाइनमेंट ऑपरेटर redeclare करने के लिए प्रयोग करें। उदाहरण

#include <iostream> 

class A 
{ 
public: 
    double x,y; 
    A(): x{0}, y{0} {} 
    virtual A & operator =(double g){ x = g; y = g; return *this; } 
    virtual ~A(){} 
}; 


class B: public A 
{ 
public: 
    B() : A(){} 
    virtual B & operator =(double g) override { A::operator =(2 * g) ; return *this; } 
    virtual ~B(){} 
}; 

int main() 
{ 
    A a; 
    B b; 

    A *p = &a; 

    *p = 10; 

    std::cout << p->x << ' ' << p->y << std::endl; 

    p = &b; 

    *p = 10; 

    std::cout << p->x << ' ' << p->y << std::endl; 

    return 0; 
} 

के लिए कार्यक्रम उत्पादन

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