2009-11-07 13 views
10

मेरे होमवर्क में, मुझे कक्षा संदेश डिज़ाइन करना होगा; अन्य विशेषताओं के बीच, इसमें "प्राथमिकता" विशेषता है (मुख्य लक्ष्य प्राथमिकता कतार लागू करना है)।एक ही कक्षा में ऑपरेटर <और ऑपरेटर> को ओवरलोड करना

कंटेनर के रूप में मुझे यह जांचना होगा कि एक वस्तु दूसरे से अधिक है, तो मैंने ऑपरेटर '>' अधिभारित किया है।

अगर मैं ऑपरेटर '>' ओवरलोड, मैं तर्क के लिए (स्थिरांक संदेश &, स्थिरांक संदेश & ऑपरेटर '<' ओवरलोड चाहिए: अब, मैं इसके बारे में कुछ सामान्य प्रश्नों ...

प्रश्न एक है)?

मेरे राय है कि> दोनों ओवरलोडिंग और < और कोड में इसका उपयोग करने में कोई त्रुटि उत्पन्न होगा है:

if(message1 > message2) 
    { ... } 

(निम्नलिखित कोड message1 वस्तु के लिए कहता है क्या ऑपरेटर>, या ऑपरेटर < आपत्ति message2?)

लेकिन, क्या हुआ अगर मैं इस तरह ऑपरेटर का उपयोग करें:

if(message1 < message2) 
    { ... } 

?

friend bool operator>(const Message& m1, const Message& m2) 

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

ऑपरेटर> दोस्त समारोह के रूप में घोषित किया जाता है?

धन्यवाद।

उत्तर

21

If I overload operator '>', should I overload operator '<' for argumenst (const Message&, const Message&)?

हां। वास्तव में, <> से अधिक (मुझे क्यों नहीं, शायद ऐतिहासिक क्यों) के उपयोग को प्राथमिकता देने के लिए अधिकांश कोड में यह सम्मेलन है। लेकिन अधिक आम तौर पर, हमेशा संबंधित ऑपरेटरों के पूरे सेट को अधिभारित करते हैं; आपके मामले में, यह शायद ==, !=, <= और >= भी होगा।

(Does the following code calls operator > for message1 object, or operator < message2 object?)

यह हमेशा कोड में जो मिलता है उसे कॉल करता है। सी ++ कंपाइलर के लिए, > और < के बीच बिल्कुल कोई कनेक्शन नहीं है। हमारे लिए, वे समान दिखते हैं लेकिन संकलक दो पूरी तरह से अलग, असंबंधित प्रतीकों को देखता है। तो कोई अस्पष्टता नहीं है: संकलक कॉल करता है जो इसे देखता है।

Does it need to be declared as member function?

नहीं। वास्तव में, यह सदस्य कार्य के रूप में घोषित नहीं किया गया है। इसे सदस्य फ़ंक्शन के रूप में घोषित करने का अर्थ है कि पहली तर्क (यानी अभिव्यक्ति का बाएं हाथ) वास्तव में Message ऑब्जेक्ट होना चाहिए, जो किसी ऑब्जेक्ट की बजाय Message पर परिवर्तनीय है।

struct RealFraction { 
    RealFraction(int x) { this.num = x; this.den = 1; } 
    RealFraction(int num, int den) { normalize(num, den); } 
    // Rest of code omitted. 

    bool operator <(RealFraction const& rhs) { 
     return num * rhs.den < den * rhs.num; 
    } 
}; 

अब आप निम्नलिखित तुलना लिख ​​सकते हैं::

int x = 1; 
RealFraction y = 2; 
if (y < x) … 

लेकिन आप निम्नलिखित नहीं लिख सकते हैं:

if (x < y) … 

इस बात को समझ करने के लिए निम्न मामले पर विचार

हालांकि 01 से एक निहित रूपांतरण मौजूद हैसे RealFraction (पहले कन्स्ट्रक्टर का उपयोग करके)।

यदि दूसरी तरफ, आपने ऑपरेटर को लागू करने के लिए एक गैर-सदस्यीय फ़ंक्शन का उपयोग किया था, तो तुलना दोनों काम करेंगे क्योंकि सी ++ पहले तर्क पर एक अंतर्निहित कन्स्ट्रक्टर को कॉल करना जानता है।

+0

धन्यवाद, मैंने कहीं पढ़ा है कि अगर मैं एक संबंध आपरेशन ओवरलोड, यह उन सभी को ओवरलोड तर्कसंगत लगता है। –

+0

और मित्र/सदस्य उत्तर के बारे में धन्यवाद। मुझे पता है तुम्हारा क्या मतलब है :)। –

+3

यह उत्तर यह भी इंगित करना चाहिए कि अधिकांश रिलेशनल ऑपरेटरों को कुछ हद तक ऑपरेटरों के मामले में वर्णित किया जा सकता है, आमतौर पर '<' और '=='।उदाहरण के लिए, 'ऑपरेटर> =' लिखा जा सकता है: 'bool ऑपरेटर> = (स्थिरांक टी एंड एल, स्थिरांक टी एंड आर) {वापसी (एल greyfade

8

हाँ, आप चाहिए ... लेकिन आप (और यकीनन चाहिए) एक दूसरे के मामले में < के तीन, >, <=, >= लागू कर सकते हैं। यह सुनिश्चित करता है कि वे लगातार व्यवहार करते हैं। आम तौर पर < वह है जिसे दूसरों को लागू किया जाता है क्योंकि यह set एस और map एस में उपयोग किया जाने वाला डिफ़ॉल्ट ऑपरेटर है।

उदा। यदि आपने < लागू किया है, तो आप >, <= और >= को इस तरह परिभाषित कर सकते हैं।

inline bool operator>(const Message& lhs, const Message& rhs) 
{ 
    return rhs < lhs; 
} 

inline bool operator<=(const Message& lhs, const Message& rhs) 
{ 
    return !(rhs < lhs); 
} 

inline bool operator>=(const Message& lhs, const Message& rhs) 
{ 
    return !(lhs < rhs); 
} 

== और != अक्सर अलग से लागू किया जाता है। कभी-कभी कक्षाएं == को लागू करती हैं जैसे कि a == b अगर और केवल !(a < b) && !(b < a) पर, लेकिन कभी-कभी == को !(a < b) && !(b < a) से कठोर रिश्ते के रूप में कार्यान्वित किया जाता है। ऐसा करने से क्लास के क्लाइंट के लिए अधिक जटिलता होती है, हालांकि। <, >, <= और >= नहीं बल्कि == या != के लिए

में कुछ स्थितियों में स्वीकार्य हो सकता है।

+1

हां, हाँ, हाँ! मैं इसका उल्लेख करना भूल गया लेकिन यह महत्वपूर्ण है। आपको शायद यह भी कहना चाहिए कि आपका साफ कोड * जितना कुशल होगा * प्रत्येक तुलना को मैन्युअल रूप से और स्वतंत्र रूप से कोडिंग के रूप में। यह काफी महत्वपूर्ण है क्योंकि इसका मतलब है कि प्रदर्शन के पक्ष में इस सलाह को पूर्ववत करने का कोई भी प्रयास समयपूर्व अनुकूलन है। –

+2

इस तरह के एक भी शॉर्ट-कट ले जा सकते हैं, जैसे 'वर्ग संदेश के रूप में: को बढ़ावा देने :: less_than_comparable <संदेश, संदेश>', और '' rel_ops' में '(उत्तरार्द्ध गंध कुछ हद तक संदिग्ध है क्योंकि वे एक का उपयोग करके useable बना रहे हैं घोषणा)। दोनों 'ऑपरेटर <' के साथ पर्याप्त है, और अन्य इसके संदर्भ में लागू हो जाते हैं। – UncleBens

+0

OTOH, 'rel_ops' उपयोग करने की कोशिश बहुत दर्द हो _can_। आम तौर पर आपको उन्हें किसी अन्य नामस्थान में आयात करना होता है और वे बहुत लालची होते हैं। अपने वर्ग ग्लोबल नेम स्पेस में है, तो आप अनुपयुक्त प्रकार के सभी प्रकार के लिए 'rel_ops' उपलब्ध कराने तुलना के साथ खत्म हो सकता है। –

4

यदि असाइनमेंट को ऑपरेटर ओवरलोडिंग के उपयोग की स्पष्ट रूप से आवश्यकता नहीं है, तो आप फ़ंक्शन ऑब्जेक्ट का उपयोग करने पर भी विचार कर सकते हैं। इसका कारण यह है कि "कम से कम" के लिए दो संदेशों की तुलना करने के लिए शायद एक से अधिक तरीके हैं (उदाहरण के लिए सामग्री लेक्सिकोग्राफिक रूप से, समय पोस्ट आदि की तुलना करें), और इसलिए operator< का अर्थ सहज रूप से स्पष्ट नहीं है।

std::priority_queue के साथ उपयोग करने के लिए समारोह वस्तु तीसरे टेम्पलेट पैरामीटर के रूप में निर्दिष्ट किया जाता है (दुर्भाग्य से आप भी दूसरे का उल्लेख करना होगा - अंतर्निहित कंटेनर प्रकार):

#include <queue> 
#include <string> 
#include <functional> 
#include <vector> 

class Message 
{ 
    int priority; 
    std::string contents; 
    //... 
public: 
    Message(int priority, const std::string msg): 
     priority(priority), 
     contents(msg) 
    {} 
    int get_priority() const { return priority; } 
    //... 
}; 

struct ComparePriority: 
    std::binary_function<Message, Message, bool> //this is just to be nice 
{ 
    bool operator()(const Message& a, const Message& b) const 
    { 
     return a.get_priority() < b.get_priority(); 
    } 
}; 

int main() 
{ 
    typedef std::priority_queue<Message, std::vector<Message>, ComparePriority> MessageQueue; 
    MessageQueue my_messages; 
    my_messages.push(Message(10, "Come at once")); 
} 

जब अपनी खुद की प्राथमिकता कतार को लागू करने के लिए, आप निम्नलिखित तरीके से इसके बारे में जा सकते हैं:

class MessageQueue 
{ 
    std::vector<Message> messages; 
    ComparePriority compare; 
    //... 
    void push(const Message& msg) 
    { 
     //... 
     if (compare(msg, messages[x])) //msg has lower priority 
     //... 
    } 
}; 
संबंधित मुद्दे