हम

2016-02-19 7 views
5

मैं सी ++ में एक वर्ग को लागू करने की कोशिश कर रहा हूँ सी में एक वर्ग ++ भीतर hashCode विधि परिभाषित कर सकता हूँ, और मैं प्रत्येक वर्ग चाहते hashCode के अपने स्वयं के कार्यान्वयन (मूल रूप से unordered_map & unordered_set में एक महत्वपूर्ण के रूप में उपयोग करने के लिए)हम

के लिए

उदाहरण के लिए:

class CustomClass{ 
    int a; 
    vector<int> b; 
    string c; 

    bool operator ==(const CustomClass& o) const{ 
     return ((a == o.a) && (b == o.b) && (c == o.c)); 
    } 

    /* 
    Is it possible to define the hashcode function here instead of defining it outside the class. 
    size_t operator()() const { 
     // Some custom logic for calculating hash of CustomClass using 
     // the hash Values of its individual fields 

     std::size_t h = 0; 
     for(int& t : b){ 
      h = (h^std::hash<int>()(t)) << 1; 
     } 
     return (h^(std::hash<int>()(a) << 1))^(std::hash<string>()(c) << 1); 
    } 
    */ 
}; 

अब, मान लीजिए मैं

int main(){ 
    unoredered_map<CustomClass, int> m; 
} 

की तरह एक unordered_map में इस का उपयोग करना चाहते मैं दो opti है ऑन,

i) टेम्पलेट विशेषज्ञता के साथ एसटीडी नाम स्थान में hashCode सम्मिलित करें

namespace std { 
    template <> struct hash<CustomClass> { 
    size_t operator()(const CustomClass& o) const { 
     // Some custom logic for calculating hash of CustomClass using 
     // the hash Values of its individual fields 

     size_t h = 0; 
     for(int& t : o.b){ 
      h = (h^std::hash<int>()(t)) << 1; 
     } 
     return (h^(std::hash<int>()(o.a) << 1))^(std::hash<string>()(o.c) << 1); 
    } 
    }; 
} 

या

ii।), जबकि unordered_map (या unordered_set) हर बार बनाने के दौरान यह instantiating, यानी इस समारोह को निर्दिष्ट करें

struct HashSpecialer { 
    std::size_t operator()(const CustomClass& o) const { 
     std::size_t h = 0; 
     for(int& t : o.b){ 
     h = (h^std::hash<int>()(t)) << 1; 
     } 
     return (h^(std::hash<int>()(o.a) << 1))^(std::hash<string>()(o.c) << 1); 
    } 
}; 

और unordered_map को तत्काल करते समय, मैंने यह संरचना प्रदान की है।

int main(){ 
    unoredered_map<CustomClass, int, HashSpecialer> m; 
} 

मुझे लगता है दोनों तरीकों (i) एसटीडी नाम स्थान को प्रदूषित करता है और (ii) यह मुश्किल बना देता है HashSpecializer हर बार जब मैं एक unordered_map

का दृष्टांत प्रदान करने के लिए याद करके उपयोग करने के लिए भ्रमित करने के लिए यह संभव है जैसा कि मैंने


से ऊपर कोड स्निपेट में टिप्पणी अनुभाग में वर्णित है, जैसा कि मैंने कक्षा में हैशकोड() विधि को ओवरराइड कर दिया है और हम इस कार्यक्षमता को प्राप्त कर सकते हैं। एक बार जब मैं हैशकोड() विधि को ओवरराइड करता हूं, तो मुझे इसके बारे में चिंता करने की आवश्यकता नहीं है।

public class CustomClass { 
    int a; 
    List<Integer> b; 
    String c; 

    // I Let my IDE generate these methods :D 
    @Override public boolean equals(Object o) 
    { 
     if (this == o) 
      return true; 
     if (o == null || getClass() != o.getClass()) 
      return false; 

     CustomClass that = (CustomClass) o; 

     if (a != that.a) 
      return false; 
     if (b != null ? !b.equals(that.b) : that.b != null) 
      return false; 
     return c != null ? c.equals(that.c) : that.c == null; 

    } 

    // This one too :D 
    @Override public int hashCode() 
    { 
     int result = a; 
     result = 31 * result + (b != null ? b.hashCode() : 0); 
     result = 31 * result + (c != null ? c.hashCode() : 0); 
     return result; 
    } 
} 

मैं ऐसा कुछ ढूंढ रहा हूं क्योंकि यह बहुत आसान साबित होता है।

+2

'std :: हैश' की विशेषज्ञता उचित खेल है। Http://en.cppreference.com/w/cpp/utility/hash/operator() पर नमूना कोड देखें। –

+1

@RSahu Thats जो मैं अब उपयोग करता हूं। मुझे यह पसंद क्यों नहीं है, इसका एक कारण यह है कि मुझे यकीन नहीं है कि अगर मैं अपने कस्टम क्लास को अलग-अलग फ़ील्ड के साथ एक से अधिक नामस्थान में परिभाषित करता हूं तो मैं स्थिति को कैसे संभाल सकता हूं। यहां तक ​​कि अगर मैं इससे दूर हो सकता हूं, तो यह कोड को पढ़ने में निश्चित रूप से भ्रमित है। मैं अभी भी इस परिदृश्य को संभालने के जावा के तरीके को पसंद करता हूं। – Anoop

उत्तर

4

मुझे लगता है कि आपकी समस्या का समाधान सौंदर्य की दृष्टि से आकर्षक सी ++ प्रोग्राम की समझ को समायोजित करना है।

std::hash का एक विशेषज्ञता एसटीडी नामस्थान को दूषित नहीं करता है, बजाय आप पर विचार करना चाहिए कि std::hash अनुकूलन बिंदु है नियंत्रित करने के लिए कैसे अपने वर्ग के साथ unordered_map काम करता है।

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

1

मुझे यकीन है कि मैं कैसे स्थिति से निपटने करते हैं CustomClass एक से अधिक नाम स्थान

है यही कारण है कि नामस्थान के लिए कर रहे हैं में परिभाषित किया गया है नहीं कर रहा हूँ। आपकी समस्या स्वयं हल हो जाती है :)

namespace std { 
    template <> struct hash<NameSpace1::CustomClass> { ... }; 
    template <> struct hash<NameSpace2::CustomClass> { ... }; 
} 

सी ++ जावा नहीं है। आप जानते हैं कि किसी भी जावा को भूल जाओ, यह आपको बहुत मदद करेगा।बहुत सारे जावा मुहावरे सी ++ में बहुत अलग दिखते हैं, या सी ++ में बस बेकार या अपरिहार्य हैं।

1

सी ++ का डिज़ाइन एक नज़र में अधिक वर्बोज़ और बोझिल हो सकता है, लेकिन यह वास्तव में अधिक लचीला है। हैश कोड के बारे में जानने के लिए सभी कक्षाएं पर नहीं हैं; और विभिन्न कंटेनरों को निहित प्रकारों में घुसपैठ किए बिना विभिन्न हैश बाधाओं की आवश्यकता हो सकती है।

यही विशेषज्ञता के बारे में इतना अच्छा है। आप अपने कोड को मानक लाइब्रेरी में वास्तव में प्रभावित किए बिना हुक कर सकते हैं। आखिरकार, आप अपने स्वयं के प्रकार के लिए विशेषज्ञता प्राप्त कर रहे हैं, इसलिए यह घुसपैठ नहीं कर रहा है।

आपके प्रकार के लिए std::hash() विशेषज्ञता इस प्रकार पूरी तरह से ठीक है, जब तक कि आप इसे उचित डिफ़ॉल्ट के रूप में उपयोग करने का इरादा रखते हैं। अन्यथा, आप std::unordered_map और आपके कुंजी प्रकार के संयोजन के लिए उपनाम टेम्पलेट पर विचार करना चाह सकते हैं।