2013-04-03 9 views
6

मेरे पास दो वैश्विक हैं, दो वैश्विक friend oparator<< एस के साथ।ग्लोबल ऑपरेटर और पॉलिमॉर्फिज्म

class A { 
    friend std::ostream& operator<<(std::ostream& o, const A &a); 
}; 

class B: public A { 
    friend std::ostream& operator<<(std::ostream& o, const B &b); 
}; 

तो मैं इस तरह उपयोग, सब कुछ ठीक काम कर रहा है, ऑपरेटर की B संस्करण कहा जाता हो जाता है:

B b; 
std::cout << b; 

लेकिन अगर मैं पोलिमोर्फ़िज्म उपयोग करते हैं, A संस्करण कहा जाता हो जाता है, हालांकि गतिशील प्रकार B है:

A* b = new B(); 
std::cout << *b; 

एक समाधान कास्टिंग है:

std::cout << static_cast<B&>(*b); 

लेकिन क्या इसके लिए कोई आसान या अधिक सुरुचिपूर्ण समाधान है?

+2

'ऑपरेटर << (std :: ostream &, a const &) 'में वर्चुअल फ़ंक्शन का आविष्कार करने के बारे में क्या? – dyp

उत्तर

10

हां। कक्षाओं में एक आउटपुट ऑपरेटर और virtual print फ़ंक्शन। जब आप आधार वर्ग के लिए सूचक से उन तक पहुँच यदि आप उन्हें virtual के रूप में परिभाषित व्युत्पन्न वर्ग में कार्यों की

class A 
{ 
public: 
    virtual ~A() {} 
private: 
    virtual void print(std::ostream&) {} 
    friend std::ostream& operator << (std::ostream& os, const A& obj) 
    { 
     obj.print(os); 
     return os; 
    } 
}; 

class B 
{ 
private: 
    virtual void print(std::ostream&) {} 
}; 

Live example

+0

कृपया मित्र समारोह में 'वापसी ओएस;' जोड़ें। – scones

+1

कृपया उस फ़ंक्शन से 'मित्र' को हटा दें - इसे एक मित्र होने की आवश्यकता नहीं है लेकिन एक नि: शुल्क फ़ंक्शन हो सकता है;) –

+0

@ArneMertz प्रिंट निजी है। ऑपरेटर << इस मामले में मुफ्त फ़ंक्शन कैसे हो सकता है? और हमें सार्वजनिक रूप से प्रिंट की आवश्यकता क्यों है? – ForEveR

3

संस्करण केवल कहा जाता है क्योंकि संकलक एक सुराग नहीं है क्या की कक्षा पॉइंटर वास्तव में इंगित वस्तु है। एक के operator<< कॉल A में एक आभासी समारोह है कि आप तो B में ओवरलोड कर सकते हैं के कार्यान्वयन है

यहाँ दिक्कत यह है कि आप दोस्त कार्यों को परिभाषित कर रहे हैं ताकि वे खुद को आभासी नहीं किया जा सकता, समाधान सरल है।

2

बस दोस्तों का उपयोग न करें। वे विरासत की तुलना में एक कड़ा युग्मन भी हैं। विशेष रूप से यदि आप क्लास टेम्पलेट्स के लिए उन मित्र ऑपरेटरों को लिखते हैं तो कोई इसे विशेषज्ञ बना सकता है और कानूनी रूप से आपके वर्ग के आंतरिक लोगों तक पहुंच प्राप्त कर सकता है। उन कारणों से मैं उन ऑपरेटरों का उपयोग केवल सिंटैक्टिक चीनी के रूप में करता हूं और उन्हें वास्तविक कार्य करने वाले सदस्य कार्यों में प्रतिनिधि होने देता हूं।

class A { 
public: 
    virtual std::ostream& printToStream(std::ostream& os) const; 
}; 

std::ostream& operator<<(std::ostream& os, A const& a) 
{ return a.printToStream(os); } 

class B: public A { 
    virtual std::ostream& printToStream(std::ostream& os) const; 
}; 

अन्य वर्ग सी एक से ली गई है: इस तरह से अपनी समस्या का हल एक चाहती हैं? कोई समस्या नहीं, सिंटैक्टिक चीनी (यानी operator<<) को फिर से परिभाषित करने की कोई आवश्यकता नहीं है, बस परिभाषित करें कि असली काम कैसे किया जाता है, यानी printToStream ओवरराइड करें - यही कारण है कि मैंने इसे वर्चुअल बना दिया।

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