2012-03-15 18 views
13

मैं इस तरह कुछ घटनाओं हैफोर्स बुला आधार वर्ग आभासी समारोह

class Granpa // this would not be changed, as its in a dll and not written by me 
{ 
public: 

    virtual void onLoad(){} 

} 

class Father :public Granpa // my modification on Granpa 
{ 
public: 

    virtual void onLoad() 
    { 
     // do important stuff 
    } 

} 

class Child :public Father// client will derive Father 
{ 

    virtual void onLoad() 
    { 
     // Father::onLoad(); // i'm trying do this without client explicitly writing the call 

     // clients code 
    } 
} 

वहाँ वास्तव में पिता :: ऑनलोड() लिखे बिना बुला ऑनलोड मजबूर करने के लिए एक तरीका है?

hackish समाधान स्वागत है :)

+4

मुझे समझ में नहीं आता कि यह एक समस्या क्यों है। आप स्पष्ट रूप से कुछ करना चाहते हैं, इसलिए आपको कोड में स्पष्ट रूप से ऐसा कहना होगा ... –

+2

क्या यह थोड़ा आलसी है कि आप कुछ ऐसा करने के लिए कोड की एक पंक्ति जोड़ना न करें जिसे आप स्पष्ट रूप से करना चाहते हैं? –

+0

यानी एमएफसी हैंडलर में एक ही समस्या हल नहीं होती है (आपको हमेशा अपने सीएमडियलॉग :: OnInitDialog() से सीडीअलॉग :: OnInitDialog() को स्पष्ट रूप से कॉल करने की आवश्यकता है, मुझे लगता है कि आपको केवल उपयोगकर्ता को ऐसा करने की आवश्यकता हो सकती है। – Mikhail

उत्तर

24

अगर मैं सही ढंग से समझ, आप इसे इतना है कि जब भी ओवरराइड समारोह बुलाया जाता है, आधार स्तरीय कार्यान्वयन हमेशा पहले कहा जाता हो जाना चाहिए चाहते हैं। इस मामले में, आप template pattern की जांच कर सकते हैं। कुछ ऐसा:

class Base 
{ 
public: 
    void foo() { 
     baseStuff(); 
     derivedStuff(); 
    } 

protected: 
    virtual void derivedStuff() = 0; 
private: 
    void baseStuff() { ... } 
}; 

class Derived : public Base { 
protected: 
    virtual void derivedStuff() { 
     // This will always get called after baseStuff() 
     ... 
    } 
}; 
+2

गैर-वर्चुअल इंटरफ़ेस के रूप में भी जाना जाता है (हालांकि मैं इसे हमेशा टेम्पलेट विधि पैटर्न के रूप में जानता हूं)। –

+0

derivedStuff दोनों कक्षाओं में भी निजी हो सकता है। – Dan

+2

यहां एक अच्छी व्याख्या भी मिल सकती है http://www.gotw.ca/publications/mill18.htm – pmr

4

जैसा ऊपर बताया गया है लेकिन आपके मामले पर लागू किया गया है।

class Father :public Granpa // my modification on Granpa 
{ 

public: 

    virtual void onLoad() 
    { 
     // do important stuff 
     onLoadHandler(); 
    } 
    virtual void onLoadHandler()=0; 
} 

class Child :public Father// client will derive Father 
{ 

    virtual void onLoadHandler() 
    { 

     // clients code 
    } 
} 

हालांकि, कुछ भी नहीं रोका जा सकता है बाल ऑनलोड ओवरराइड करने के लिए के बाद से C++ कोई अंतिम कीवर्ड है और Granpa ऑनलोड ही आभासी है।

+4

सौभाग्य से, सी ++ 11 में अंतिम कीवर्ड है। – juanchopanza

2

ठीक है, ऐसा करने के लिए कोई व्यापक रूप से ज्ञात, मान्यता प्राप्त तरीका नहीं है। यदि वहां होता है, तो घटनाओं और संकेतों का उपयोग करने वाले जीयूआई पुस्तकालयों ने शायद इसे लागू किया होगा। हालांकि आपकी समस्या के अन्य समाधान भी हैं।

आप boost.Signals, sigslot या अपने स्वयं के बनाने का उपयोग करके सिग्नल-इवेंट कनेक्शन को कार्यान्वित कर सकते हैं। जीटीके + करता है:

g_signal_connect(my_wdg, "expose-event", G_CALLBACK(my_func), NULL); 

gboolean my_func(...) 
{ 
    // do stuff 
    return FALSE; /* this tells the event handler to also call the base class's slot */ 
} 

एक कम सी केंद्रित तरह से, यह इन पंक्तियों के साथ लागू किया जा सकता:

/* In Granpa */ 
/* typedef a functor as 'DerivedEventHandler' or use a boost::function */ 
std::vector<DerivedEventHandler> handlers; 

void connect(DerivedEventHandler event) { handlers.push_back(event); } 

/* in loop */ 
while (! iter = handlers.end()) /* call event */ 

/* In constructor of Father */ 
this->connect(this->OnLoad); 

/* In constructor of Child */ 
this->connect(this->OnLoad); 

/* and so on... in all derived classes */ 
-1

तो सवाल में वस्तु छोटे और सस्ते कॉपी करने के लिए, बस आधार कहते हैं वर्ग 'कॉपी कन्स्ट्रक्टर, यानी बेसक्लास (* derived_class_object) .method()

+0

शायद ओपी चाहता था कि नहीं, क्योंकि उसने पूछा कि बेसक्लास फ़ंक्शन कॉल को स्पष्ट रूप से लिखने के तरीके के बारे में क्या करना है, जिसे आपको इस दृष्टिकोण के साथ भी करना होगा। – Haatschii

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