2012-03-29 27 views
9

मुझे ऐसी समस्या हल करने की आवश्यकता है। एक बेस क्लास और दो विरासत कक्षाएं हैं। बेस क्लास में ऐसी विधि होती है जिसे पैरामीटर के रूप में फ़ंक्शन-पॉइंटर की आवश्यकता होती है। लेकिन ऐसे कार्यों को विरासत कक्षाओं में परिभाषित किया गया है।सदस्य-फ़ंक्शन पॉइंटर्स और विरासत

त्रुटि C2664: 'CBase :: WaitEvent':

class CBase; 

typedef bool (CBase::*FPredicate)(); 

class CBase 
{ 
public: 
    CBase() {} 
    ~CBase() {} 
protected: 
    //this method waits until 'predicate' is true or until 'timeout' ms. passed 
    //and returns true if 'predicate' is true eventually 
    bool WaitEvent(FPredicate predicate, int timeout) 
    { 
     bool result = false; 
     int time1 = GetTickCount(); 
     int time2; 

     bool isEnd = false; 
     while(!isEnd) 
     { 
      result = isEnd = (this->*predicate)();    

      time2 = GetTickCount(); 
      if(time2 - time1 > timeout && !isEnd) 
       isEnd = true; 
     } 
     return result; 
    } 
}; 

class CChildA : public CBase 
{ 
protected: 
    bool a1() {/*some work*/} 
    bool a2() {/*some work*/} 
    void a_main() 
    { 
     ... 
     WaitEvent(&CChildA::a1, 100); 
     ... 
     WaitEvent(&CChildA::a2, 100); 
     ... 
    } 
}; 

class CChildB : public CBase 
{ 
protected: 
    bool b1() {/*some work*/} 
    bool b2() {/*some work*/} 
    void b_main() 
    { 
     ... 
     WaitEvent(&CChildB::b1, 100); 
     ... 
     WaitEvent(&CChildB::b2, 100); 
     ... 
    } 
}; 

MSVC 2005 संकलक WaitEvent पर एक त्रुटि कॉल देता है 'bool से पैरामीटर 1 परिवर्तित नहीं कर सकते (__thiscall CChildA :: *) (शून्य) 'to' FPredicate '

एक प्रश्न है: मैं इसे काम करने के लिए कोड कैसे बदलूं? क्या WaitEvent कॉल को WaitEvent((FPredicate)(&CChildA::a1), 100) के रूप में फिर से लिखना सुरक्षित होगा?

इस मामले में संकलक कोई त्रुटि नहीं बताता है लेकिन यह सुरक्षित है? या क्या समस्या हल करने का एक बेहतर तरीका है?

अग्रिम धन्यवाद।

+0

कोई भी मौका आप बूस्ट या std :: tr1 का उपयोग कर सकते हैं? उस स्थिति में आप केवल फ़ंक्शन का उपयोग करेंगे और व्युत्पन्न क्लास में बाइंड() को सदस्य फ़ंक्शन – stijn

+0

@stijn के साथ उपयोग करें, याद रखें, सी ++ 11 लाइव है और 'बाइंड()' पहले से ही 'std ::' । और यह आमतौर पर -std = C++ 0x का उपयोग करने के लिए फायदेमंद है, क्योंकि कुछ छोटी विशेषताएं, जो रोजमर्रा की प्रोग्रामिंग में मदद करती हैं, पहले ही प्रयोग योग्य हैं। – Griwes

+0

क्या आप आधार वर्ग से व्युत्पन्न कक्षाओं में कॉल करने योग्य कार्य कर सकते हैं? दुर्भाग्यवश, –

उत्तर

3

समस्या यह है कि अंतर्निहित रूप से यह प्रकार में भिन्न होता है। या तो आप इसे कास्ट करते हैं, लेकिन यह शायद कई विरासत की उपस्थिति में असफल हो जाएगा। एक बेहतर & और अधिक मजबूत समाधान के लिए हस्ताक्षर बदलने के लिए होगा:

template< typename T > 
bool WaitEvent(bool (T::*predicate)(), int timeout) { ... } 
+0

धन्यवाद, मुझे लगता है कि मैं अपनी पहली पोस्ट में वर्णित एक कलाकार बनाउंगा।जिस तरह से मैंने कुछ परीक्षण चलाए और वे ठीक थे। इसलिए क्योंकि कोई भी विरासत नहीं होगी, कोई समस्या नहीं होनी चाहिए। –

3

आप इसे बचत यह सही प्रकार है अपने बच्चे को वस्तु और अपने कार्य सदस्य के एक बंद करने के लिए एक टेम्पलेट वर्ग का उपयोग कर सकते हैं। और उसके बाद बेस क्लास को सामान्य बहुरूपता के माध्यम से कॉल करने के लिए आभासी कार्यों का उपयोग करना।

विनाशकों को कॉल करने के लिए shared_ptr में एक समान तंत्र का उपयोग किया जाता है। देखें: http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Advanced-STL-1-of-n

#include <iostream> 

struct CPredicateBase 
{ 
     virtual ~CPredicateBase() {} 
     virtual bool operator()() = 0; 
}; 

template <class T> 
struct CPredicate : public CPredicateBase 
{ 
     bool (T::*func)(); 
     T* self; 

     CPredicate(T* self_, bool (T::*func_)()) 
     : func(func_), self(self_) {} 

     bool operator()() { return (self->*func)(); } 
}; 

class CBase 
{ 
public: 

     bool WaitEvent(CPredicateBase& predicate, int imeout) 
     { 
       /// just to show the call 
       bool b = predicate(); 
       std::cout << "WaitEvent called predicate() => " << b << std::endl; 
       return b; 
     } 
}; 


class CChildA : public CBase 
{ 
public: 
     bool a1() { return false; } 
     bool a2() { return true; } 

     void a_main() 
     { 
       std::cout << "CChildA::a_main()" << std::endl; 
       CPredicate<CChildA> caller1(this, &CChildA::a1); 
       bool ra1 = WaitEvent(caller1, 100); 
       CPredicate<CChildA> caller2(this, &CChildA::a2); 
       bool ra2 = WaitEvent(caller2, 100); 
     } 
}; 

class CChildB : public CBase 
{ 
public: 
     bool b1() { return false; } 
     bool b2() { return true; } 

     void b_main() 
     { 
       std::cout << "CChildB::b_main()" << std::endl; 
       CPredicate<CChildB> caller1(this, &CChildB::b1); 
       bool rb1 = WaitEvent(caller1, 100); 
       CPredicate<CChildB> caller2(this, &CChildB::b2); 
       bool rb2 = WaitEvent(caller2, 100); 
     } 
}; 

int main(int argc, char const* argv[]) 
{ 
     CChildA cA; 
     CChildB cB; 

     cA.a_main(); 
     cB.b_main(); 

     return 0; 
} 
संबंधित मुद्दे