2011-10-07 9 views
8

मुझे बेस क्लास और फिर कई व्युत्पन्न कक्षाएं मिली हैं। मैं इन व्युत्पन्न कक्षाओं के लिए "< <" ऑपरेटर को अधिभारित करना चाहता हूं। सामान्य ऑपरेटरों के लिए, यानी '+', आभासी कार्य चाल करते हैं। मैं मानक सम्मेलन के रूप में समझता हूं किओवरलोडिंग << ऑपरेटरों और विरासत कक्षाएं

friend ostream& operator<<(ostream& out, MyClass& A); 

मेरी कक्षा के भीतर घोषित करना है और फिर वर्ग के बाद फ़ंक्शन को परिभाषित करना है। एक प्राथमिकता मुझे लगता है कि उपरोक्त परिभाषा में वर्चुअल जोड़ने से यह काम करेगा, लेकिन कुछ विचारों के बाद (और मेरे कंपाइलर से त्रुटियां) मुझे एहसास है कि ज्यादा समझ में नहीं आता है।

मैंने परीक्षण मामले पर एक अलग प्रयास करने की कोशिश की, जहां सभी वर्ग के सदस्य सार्वजनिक हैं। उदाहरण के लिए: - आधार वर्ग ऑपरेटर < < व्युत्पन्न वर्ग ऑपरेटर के बजाय बुलाया जा रहा है

class Foo{ 
//bla 
}; 

ostream& operator<<(ostream& out, Foo& foo){ 
    cout << "Foo" << endl; 
    return foo; 
} 

class Bar : public Foo{ 
//bla 
}; 

ostream& operator<<(ostream& out, Bar& bar){ 
    cout << "Bar" << endl; 
    return bar; 
} 

/////////////////////// 

Bar bar = Bar(); 
cout << bar << endl; // outputs 'Foo', not 'Bar' 

तो किसी तरह से इस "बहुरूपता बुरा चला गया है।" उपर्युक्त उदाहरण में, मैं व्युत्पन्न कक्षा के लिए सही ऑपरेटर कैसे कहूं? और अधिक आम तौर पर, अगर मेरी कक्षा में निजी सदस्य हैं, तो मैं रक्षा करना चाहता हूं, दोस्त मित्र का उपयोग करते समय ऑपरेटर ओवरलोडिंग को कैसे सही कर सकता हूं?

उत्तर

6

आप वर्चुअल हेल्पर फ़ंक्शन का उपयोग कर सकते हैं। यहाँ एक पूरी तरह से अपरीक्षित उदाहरण है, इसलिए किसी भी वाक्य रचना गलतियों बहाना:

virtual ostream& Foo::print(ostream& out) const { 
    return out << "Foo"; 
} 

virtual ostream& Bar::print(ostream& out) const { 
    return out << "Bar"; 
} 

// If print is public, this doesn't need to be a friend. 
ostream& operator<<(ostream& out, const Foo& foo) { 
    return foo.print(out); 
} 

संपादित करें: @Omnifarious सुझाव प्रति साफ़ किया।

+0

पूरी तरह से काम करता है। धन्यवाद। – andyInCambridge

+0

मुझे लगता है कि इसमें दो त्रुटियां हैं। एक दोष एक बड़ी खामियां है, और दूसरा मामूली दोष है। पहले भारी दोष ... आपको कभी भी 'endl' में अदृश्य रूप से नहीं डालना चाहिए। 'endl' एक स्ट्रीम फ्लश को मजबूर करता है, जो कुछ परिस्थितियों में एक बड़ी प्रदर्शन समस्या हो सकती है। ''\ N'' का प्रयोग करें। यह केवल पोर्टेबल होने की गारंटी है (वास्तव में, 'endl' को '' \ n'' आउटपुट करने के संदर्भ में परिभाषित किया गया है, और फ्लश ओवरहेड नहीं लेता है। दूसरा, मैं यह करूँगा: 'वापस लौटें <<" Foo \ n ";' थोड़ा साफ महसूस करता है। यह पूरी तरह से पूरी चीज को '<<' संचालन की लंबी श्रृंखला में बदल देता है। – Omnifarious

+0

@ ओम्निफिरियस मैं कभी भी 'ऑपरेटर' में 'एंडल' नहीं डालूंगा << 'ओवरलोड। मैं बस निम्नलिखित था ओपी का कोड –

1

operator<< एक निःशुल्क फ़ंक्शन बनाएं जो Foo कक्षा virtual विधि को कॉल करें।

See it in action

+0

हाँ यह काम करता है! धन्यवाद। – andyInCambridge

2

आमतौर पर आप बेस क्लास में एक पॉलिमॉर्फिक print विधि बनाते हैं जिसे एक एकल मित्र मित्र द्वारा बुलाया जाता है।

+0

यदि प्रिंट सार्वजनिक है, तो हम दोस्त को खा सकते हैं। –

+0

सभी के आसपास अच्छे अंक, धन्यवाद। – andyInCambridge

1

जगह में उचित कोड सुधार के साथ, आपके कोड ठीक काम करता है; कुछ भी नहीं किया जाना:

ostream& operator<<(ostream& out, Foo& foo) { 
    out << "Foo" << endl; // 'out' and not 'cout' 
    return out; // returns 'out' and not 'foo' 
} 

ostream& operator<<(ostream& out, Bar& bar) { 
    out << "Bar" << endl; // 'out' and not 'cout' 
    return out; // returns 'out' and not 'bar' 
} 

Demoprivate सदस्यों तक पहुंचने के लिए, आप वांछित class में यह फ़ंक्शन friend के रूप में बना सकते हैं।

+1

दिलचस्प। मेरे वास्तव में कोड में मैंने cout के बजाय सही ढंग से उपयोग किया था, लेकिन यह अभी भी काम नहीं कर रहा था। फिलर // ब्लै वर्गों द्वारा कब्जा नहीं किया गया है पर कुछ सूक्ष्म जा रहा होना चाहिए। – andyInCambridge