C++

2012-07-03 33 views
6

में मिश्रण-इन्स के साथ उत्सुक परिपत्र विरासत यहां परिपत्र विरासत को अनसुलझा करने का एक अच्छा तरीका क्या है?C++

class Node { 
    // ... 
public: 
    list<Node*> neighbors() { /* ... */ } 
    void update() { } 
} 

template<class NodeType> 
class HasImportance : public virtual NodeType { 
    double m_importance = 0.0; 
public: 
    void receive_importance(double imp) { /* ... */ } 
    void give_importance() { 
     for (auto neighbor : this->neighbors()) 
     neighbor->receive_importance(m_importance /* ... */); 
    } 
}; 

class TrafficLight : public HasImportance<TrafficLight>, virtual Node { 
public: 
    list<TrafficLight*> neighbors() { ... } 
    void update() { give_importance(); /* ... */ } 
}; 

यह (जीसीसी 4.7.0) में विफल रहता है क्योंकि TrafficLight जब HasImportance की कोशिश करता यह से प्राप्त करना एक अधूरी प्रकार है।

वास्तविक समस्या यह है कि हैसपोर्ट को neighbors() द्वारा लौटाए गए प्रकार को जानने की आवश्यकता है। Node से HasImportance इनहेरिट करती है, तो यह neighbors() रिटर्न TrafficLight* Node* की एक सूची, नहीं सोचता है, और फलस्वरूप पता नहीं है कि यह आइटम पर receive_importance() फोन कर सकते हैं। HasImportance पर समान समस्या का वारिस नहीं है।

बीटीडब्ल्यू, जो मैं करने की कोशिश कर रहा हूं वह विभिन्न प्रकार के ग्राफ को आसानी से परिभाषित करने में मदद करने के लिए कुछ मिश्रण-इन्स बनाता है और अलग-अलग मिश्रण में यूनिट-टेस्ट को अलग-अलग करता है। उदाहरण के लिए, मुझे लिखकर class TrafficLight : public HasImportance, HasState<3>, virtual Node { } लिखकर यातायात रोशनी के ग्राफ के लिए नोड क्लास को परिभाषित करने में सक्षम होना चाहिए।

मैं इसे हल करने के तीन तरीकों से आया हूं, लेकिन सभी बदसूरत लगते हैं। (1) static_cast<NodeType*>। (2) TrafficLight अपने कन्स्ट्रक्टर में this से HasImportance पास करता है। इस तरह, HasImportance को वारिस की आवश्यकता नहीं है; यह सिर्फ पॉइंटर से (एहेम) स्टोर करता है, और टेम्पलेट पैरामीटर पॉइंटर का प्रकार प्रदान करता है। (3) बनाने Node एक वर्ग टेम्पलेट, इस तरह:

template<class NodeType> 
class Node { 
public: 
    list<NodeType*> neighbors() { /* ... */ } 
} 

class TrafficLight : public HasImportance<Node<TrafficLight>> { /* ... */ } 

संकलित यही कारण है कि और यह this, के एक नि: शुल्क प्रतिलिपि परिचय नहीं है लेकिन ऐसा लगता है ... कुछ ज़्यादा ही उत्सुक।

क्या यहां कोई कोड गंध है? क्या मुझे इन ग्राफों को पूरी तरह से अलग-अलग तरीके से देखना चाहिए?

+11

'static_cast (यह)' सीआरटीपी में सामान्य * का उपयोग कर रहा है। – kennytm

+0

@ केनीटीएम: मैं अब तक भी जाऊंगा और कहूंगा कि यह सीआरटीपी – PlasmaHH

+0

धन्यवाद का उपयोग करने में महत्वपूर्ण है। मैं static_cast का उपयोग करने पर क्रिंग करता हूं, क्योंकि ऐसा लगता है कि मैं एक संकेत (एक "गंध") को अनदेखा कर रहा हूं कि कुछ गहरा गलत है। यदि यह सीआरटीपी में "सामान्य" है, तो मुझे लगता है कि मैं इतना विरोध नहीं करूँगा। यह मेरा पहला सीआरटीपी है। क्या तुम बता सकते हो? :) –

उत्तर

1

(3) लेकिन थोड़ा अलग।

template <class NodeType> 
class Node { ... }; 

template<class NodeType> 
class HasImportance : public virtual Node<NodeType> { ... }; 

class TrafficLight : public HasImportance<TrafficLight> { ... }; 

सीआरटीपी की तुलना में अधिक उत्सुक नहीं, मेरे लिए पूरी तरह से सरल दिखता है।

+0

धन्यवाद! मुझे यह बहुत अच्छा लगता है भले ही यह एक छोटा अंतर है। मिश्रण-इन्स में "संकलन-समय इंटरफ़ेस" अब मेरे संस्करण के विपरीत, कोड में कहीं और बदलने के लिए सरल और सुंदर प्रतिरक्षा है। –