2013-02-19 22 views
5
class Interface 
{ 
}; 

class Class : public Interface 
{ 
}; 

class Foo 
{ 
public: 
    std::vector<std::shared_ptr<Interface>>& GetInterfaces() 
    { 
     return *(std::vector<std::shared_ptr<Interface>>*)(&m_data); 
     //return m_data; 
    } 

private: 
    std::vector<std::shared_ptr<Class>> m_data; 
}; 

यह काम करता है लेकिन बदसूरत और डरावना है की share_ptrs का एक वेक्टर के लिए एक व्युत्पन्न वर्ग की shared_ptrs का एक वेक्टर कास्ट करने के लिए। क्या ऐसा करने के लिए कोई बेहतर/सुरक्षित तरीका है? मैं नहीं चाहता कि प्रकार std::vector<std::shared_ptr<Interface>> की m_data बनाने के लिए क्योंकि मॉड्यूल Foo के अंतर्गत आता है Class की, Interface (और Foo::GetInterfaces()) एक अलग मॉड्यूल है कि केवल Interface कार्यक्षमता के बारे में पता होना चाहिए के साथ बातचीत करने के लिए लागू कर रहे हैं के साथ पूरी तरह से काम करता है चाहता हूँ।कैसे एक आधार वर्ग

मुझे बताएं कि यहां कुछ भी अस्पष्ट नहीं है, यह मुझे समझ में आता है लेकिन मैं थोड़ी देर के लिए समस्या के खिलाफ अपने सिर को टक्कर लगी हूं।

उत्तर

7

कास्टिंग सही नहीं है, वे अलग-अलग प्रकार हैं; मुझे यकीन है कि आप अपरिभाषित व्यवहार का आह्वान कर रहे हैं।

आपको एक नया वेक्टर बनाने और इसे मूल्य से वापस करने की आवश्यकता है।

std::vector<std::shared_ptr<Interface>> b (m_data.begin(), m_data.end()); 
return b; 

यह अभी भी काफी सस्ते (1 आवंटन) होना चाहिए।

+0

क्या है साझा सूचक उस स्थिति में क्या करने जा रहा? मुझे यकीन नहीं है कि यह दो अलग-अलग प्रकार के साझा सूचक के बीच पॉइंटर्स साझा करना चाहता है! –

+0

@MichaelKohne नहीं यह ठीक है। – 111111

+0

आह, जीत के लिए अर्थशास्त्र चलाओ! मूल्य ठीक से वापस करना चाहिए। –

4

इसके अलावा vector के कार्यान्वयन के साथ यह संभव नहीं है, यह भी मुद्दा है कि संदर्भ परिवर्तित नहीं होते हैं। आपका कोड भी बदतर है और अपरिभाषित व्यवहार है।

आप क्या कर सकते हैं एक इंटरफ़ेस प्रदान करता है जो कंटेनर के बजाय एक श्रेणी या begin/end का खुलासा करता है। यदि आप इसे transform_iterator के साथ जोड़ते हैं जो रूपांतरण करता है, तो आपको सेट किया जाना चाहिए।

नमूना कोड:

class Interface { 
    virtual ~Interface(); 
}; 

class X : public Interface {}; 

class C { 

private: 
    typedef std::shared_ptr<Interface> iptr_type; 
    typedef std::shared_ptr<Class> ptr_type; 
    std::vector<ptr_type> v_; 

    struct F { 
    iptr_type 
    operator()(ptr_type p) { return iptr_type(p); } 
    }; 

    typedef boost::transform_iterator< 
    F, std::vector<ptr_type>::iterator> iiterator; 

public: 
    iiterator 
    begin() 
    { 
    return boost::make_transform_iterator(
     begin(v_), F()); 
    } 

    iiterator 
    end() 
    { 
    return boost::make_transform_iterator(
     end(v_), F()); 
    } 
}; 
+0

पर सरल बना सकते हैं; यदि यह आपके उपयोग के मामले में समझ में आता है तो ' .begin() 'और' .end() 'iterator इंटरफ़ेस एक अच्छा विकल्प है। – 111111

+0

@ 111111 निश्चित रूप से, वह भी। लेकिन मुझे लगता है कि रेंज अधिक हिप चीज हैं। – pmr

+0

मेरी टिप्पणी आपके विचार के समर्थन में एक थी :) – 111111

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