2012-05-09 12 views
5

का एक ptr_map है, मेरे पास boost::ptr_map है जो अमूर्त बेस क्लास (उदा। VectorWrapperBase) मानों के रूप में संग्रहीत करता है और इससे मुझे विभिन्न प्रकार के वैक्टरों के तारों को मैप करने की अनुमति मिलती है।मैपिंग ऑब्जेक्ट जिसमें अमूर्त बेस क्लासेस

boost::ptr_map<std::string, VectorWrapperBase> memory_map; 
//... 
memory_map.insert(str_key, new VectorWrapper<T>()); 

यह काम प्रतीत होता है। हालांकि, जब मेरे पास memory_map किसी अन्य वर्ग के सदस्य के रूप में है और std::map में उस वर्ग को स्टोर करने का प्रयास करता है, तो संकलन विफल हो जाता है।

class AgentMemory { 
    //... 
    private: 
    boost::ptr_map<std::string, VectorWrapperBase> memory_map; 
}; 

std::map<std::string, AgentMemory> agent_map; 
//... 
agent_map.insert(std::pair<std::string, AgentMemory>(agent_name, AgentMemory())); 

अंतिम पंक्ति में विफल रहता है के साथ:

/SOMEPATH/boost_1_48_0/boost/ptr_container/clone_allocator.hpp:34 
    error: cannot allocate an object of abstract type ‘xyz::VectorWrapperBase’ 

सी ++ के लिए नए होने के नाते, यह चौंकाने है।

मैं संदिग्ध कि त्रुटि मानचित्र प्रविष्टि AgentMemory वस्तु जो ptr_map क्लोनिंग शामिल है को कॉपी करने के लिए नीचे है। और चूंकि मेरी VectorWrapper ऑब्जेक्ट्स cloneable नहीं हैं, इसलिए त्रुटि उठाई गई है।

मेरे प्रश्न हैं:

  • मैं त्रुटि क्यों मिल रही? (क्या मेरे संदेह वास्तव में क्या हो रहा है इसके करीब भी हैं?)
  • मैं इसे कैसे संबोधित करूं?

संकलन त्रुटि के समाधान के लिए, मैं माना जाता है निम्नलिखित है, लेकिन सी के साथ ज्यादा अनुभव के बिना ++ तय नहीं कर सकता जो अधिक उपयुक्त है:

  1. शुद्ध विनिर्देशक (= 0) निकाल दें, ताकि VectorWrapperBase है अब कोई सार
    • यह एक हैक के बाद से VectorWrapperBase कभी नहीं instantiated किया जाना चाहिए
  2. VectorWrappers बनाने की तरह लगता है cloneable
    • This seems to work, लेकिन मेरे उपयोग के मामले में केवल खाली कंटेनर भीतरी ptr_map के भीतर ऐसा VectorWrappers शीर्ष स्तर के नक्शे को सौंपा है क्लोन करने की जरुरत नहीं है। इसलिए क्लोनिबिलिटी केवल कंपाइलर को खुश करने के लिए होगी और वास्तविक उपयोग को प्रतिबिंबित नहीं करती है।
  3. भूल जाओ ptr_map और एक std::map और shared_ptr बजाय का उपयोग करें।
    • मैं इस समाधान पर कम उत्सुक हूं क्योंकि मैं वेक्टर रैपर के जीवनकाल को मानचित्र के लिंक से जोड़ना चाहता हूं। मैं बहुत कम चिंतित अनुप्रयोग में shared_ptr के व्यापक उपयोग के संभावित ओवरहेड के बारे में थोड़ा चिंतित हूं (शायद अनावश्यक रूप से?)।
+0

क्या आपके सार बेस क्लास में वर्चुअल विनाशक है? – TemplateRex

+0

हां यह करता है। .. –

उत्तर

0

बयान

agent_map.insert(std::pair<std::string, AgentMemory>(agent_name, AgentMemory())); 

AgentMemory के डिफ़ॉल्ट निर्माता, जो बारी में boost::ptr_map<std::string, VectorWrapperBase> के डिफ़ॉल्ट निर्माता फोन करेगा, जो सार के लिए न के बराबर निर्माता फोन करने की कोशिश करेंगे कॉल करेंगे बेस क्लास VectorWrapperBase

तो आपको यह सुनिश्चित करना होगा कि टाइपिंग या विरासत VectorWrapperBase के प्रत्येक कन्स्ट्रक्टर को हमेशा कंक्रीट व्युत्पन्न कक्षा का निर्माण करना चाहिए। आपके मामले में, विकल्प 3 (व्युत्पन्न कक्षाओं में साझा पॉइंटर्स का नक्शा) समझदार हो सकता है, लेकिन यह आपके कोड के बड़े संदर्भ पर निर्भर करता है।

+0

स्पष्टीकरण के लिए धन्यवाद। मुझे क्या भ्रमित करता है कि 'ptr_map' खाली हो जाता है तो 'वेक्टरवापरबेस' के लिए कन्स्ट्रक्टर को कॉल करने की आवश्यकता क्यों है? –

+0

@ShawnChin जैसा कि मैंने अपने उत्तर में बताया है, 'AgentMemory()' तर्क के साथ 'insert()' कॉल कन्स्ट्रक्टर कॉल उत्पन्न करेगा। – TemplateRex

+0

शायद मुझे गलत समझा, लेकिन 'वेक्टरवॉपरबेस' 'एजेंटमेटरी 'का सदस्य नहीं है और इसलिए मुझे नहीं पता कि इसका एक उदाहरण क्यों बनाया जाना चाहिए। उस ने कहा, अब मैं इस तथ्य की सराहना करता हूं कि 'वेक्टरवार्परबेस' को क्लोनेबल होने की आवश्यकता है क्योंकि 'ptr_map' को encapsulating क्लास की कॉपी कन्स्ट्रक्टर द्वारा प्रतिलिपि बनाने की आवश्यकता है। –

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