2010-08-31 12 views
8

आगंतुक पैटर्न सबसे तेज़ तरीका विधि पैरामीटर प्रकार पहचान हासिल करने के लिए सी ++ में (प्रभावी रूप से एक प्रेषण एक पैरामीटर, नहीं एक सदस्य के वर्ग पर) है? मैं सटीक तरीका (रों) मैं नहीं अभी तक पता उप-प्रकार के तत्वों पर आह्वान करना चाहते हैं पता हो सकता है, इसलिए हमेशा A::accept(V &v) { v.visit(this); } में V::visit(A *) की तरह एक अतिरिक्त आभासी विधि कॉल करने अवांछनीय है।विज़िटर पैटर्न सी ++ में पैरामीटर प्रकारों को अलग करने का सबसे तेज़ तरीका है?

// Is the Visitor pattern recommended here? (E inherits D inherits B.) 
class Foo { 
public: 
    virtual void visit(B *) { result = 3; } 
    virtual void visit(D *) { result = 4; } 
    virtual void visit(E *) { result = 5; } 
private: 
    int result; 
}; // class Foo 

// Need to add generic interface to B and its children ... 
class B { 
public: 
    virtual void accept(class Foo &f) { f.visit(this); } 
}; // class B 

मैं कुछ कार्यात्मक रूप से बराबर निम्नलिखित लेकिन हे (1) लागत, जो AFAIK dynamic_cast <> या typeid साथ संभव नहीं है के साथ() सीढ़ी चाहते हैं, के बाद से std::type_info एक constexpr/switchable नहीं हो सकता।

// O(n) search cost might get nasty with bigger hierarchies. 
int foo(B *b) { 
    if (typeid(b) == typeid(B *)) { return 1; } 
    if (typeid(b) == typeid(D *)) { return 2; } 
    if (typeid(b) == typeid(E *)) { return 3; } 
    return -1; 
} 

यहां मेरे विकल्प क्या हैं? सलाह के लिए धन्यवाद!

संपादित करें: फ़ील्ड के माध्यम से परिणामों को खिलाने के लिए नमूना कोड बदल दिया, जैसे विभिन्न विधि प्रकारों के लिए एकाधिक हस्ताक्षर की आवश्यकता नहीं है। धन्यवाद, मौरिस!

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

+0

सी ++ 11 के बाद पाठकों के लिए: Yorel Multimethod लाइब्रेरी (जो अभी बूस्ट में है) पर एक नज़र डालें –

उत्तर

3

वास्तव में, इंटरफेस को डुप्लिकेट करने की आवश्यकता नहीं है। आगंतुक के उप-वर्ग संचालन के विवरण को संभाल सकते हैं। आपके मामले में:

class Visitor { 
    virtual void visit(B*) = 0; 
    virtual void visit(D*) = 0; 
    virtual void visit(E*) = 0; 
} 

class Foo: public Visitor { 
private: 
    int result; 
public: 
    void visit(B*) { result = 3; } 
    void visit(D*) { result = 4; } 
    void visit(E*) { result = 5; } 
    int apply(A* a) { 
     a->accept(this); 
     return result; 
    } 
} 

तो, केवल एक ही स्वीकार() विधि प्रत्येक वर्ग में की जरूरत है।

विज़िटर पैटर्न के सभी विकल्प मैं सोच सकता हूं कि कुछ प्रकार की रन-टाइम खोज शामिल है, इसलिए हाँ, आईएमएचओ, विज़िटर पैटर्न सबसे तेज़ तरीका है।

+0

आह, अच्छा बिंदु। इस परिलक्षित करने के लिए प्रश्न परिचय और नमूना कोड अपडेट किया गया। – Jeff

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

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