2012-04-20 19 views
6

के रूप में ऑपरेटर मैं कक्षा में एक विकल्प सेट के आधार पर operator() कई अलग-अलग तरीकों को लागू करना चाहता हूं। क्योंकि इसे बड़ी संख्या में बुलाया जाएगा, मैं शाखाओं के किसी भी चीज का उपयोग नहीं करना चाहता हूं। आदर्श रूप में, operator() एक फ़ंक्शन पॉइंटर होगा जिसे विधि के साथ सेट किया जा सकता है। हालांकि, मुझे यकीन नहीं है कि यह वास्तव में कैसा दिखता है। मैंने कोशिश की:फ़ंक्शन पॉइंटर

#include <iostream> 

class Test { 
public: 
    int (*operator())(); 

    int DoIt1() { 
    return 1; 
    } 

    int DoIt2() { 
    return 2; 
    } 

    void SetIt(int i) { 
    if(i == 1) { 
     operator() = &Test::DoIt1; 
    } else { 
     operator() = &Test::DoIt2; 
    } 
    } 
}; 

int main() 
{ 
    Test t1; 

    t1.SetIt(1); 

    std::cout << t1() << std::endl; 

    t1.SetIt(2); 

    std::cout << t1() << std::endl; 

    return 0; 
} 

मैं जानता हूँ कि अगर मैं एक और समारोह सूचक बना सकते हैं और फोन है कि operator() समारोह से यह काम करेंगे। लेकिन क्या operator() फ़ंक्शन स्वयं एक फ़ंक्शन पॉइंटर होना संभव है? मैंने जो पोस्ट किया है उसके साथ कुछ (जो संकलित नहीं करता है)?

ऊपर कोड देता है:

test.cxx:5:21: error: declaration of ‘operator()’ as non-function

test.cxx: In member function ‘void Test::SetIt(int)’:

test.cxx:17:16: error: ‘operator()’ not defined

test.cxx:19:16: error: ‘operator()’ not defined

test.cxx: In function ‘int main()’:

test.cxx:30:19: error: no match for call to ‘(Test)()’

test.cxx:34:19: error: no match for call to ‘(Test)()’

+0

' पूर्णांक (ऑपरेटर())():

यहाँ सी ++ 11 के लिए ही एक और समाधान है? – iammilind

+0

एचआरएम, यह 'int (* ऑपरेटर())() होना चाहिए;' मुझे लगता है, लेकिन यह सिर्फ त्रुटियों का एक और सेट उठाता है। मैं कोड संपादित करूंगा। – tpg2114

+0

"मैं शाखाओं के किसी भी चीज का उपयोग नहीं करना चाहता हूं। आदर्श रूप में, ऑपरेटर() एक फ़ंक्शन पॉइंटर होगा" - वास्तव में, प्रदर्शन प्रदर्शन के लिए शाखाएं बेहतर होती हैं। भविष्यवाणी करने के लिए आधुनिक सीपीयू की 50% सफलता दर से बेहतर है कि कौन सी शाखा ली जाएगी; फ़ंक्शन पॉइंटर्स कहीं भी इंगित कर सकते हैं और भविष्यवाणी तर्क पर बहुत कठिन हैं। – MSalters

उत्तर

5

आपका वर्ग किसी भी तरह याद करने के लिए क्या समारोह सूचक का उपयोग करने की जरूरत है। एक वर्ग के सदस्य के रूप में यह स्टोर:

class Test 
{ 
public: 
    Test() : func(0) {} 

    int operator()() { 
     // Note that pointers to Test member functions need a pointer to Test to work. 
     return (this->*func)(); // undefined behavior if func == 0 
    } 

    void SetIt(int i) { 
     if(i == 1) { 
      func = &Test::DoIt1; 
     } else { 
      func = &Test::DoIt2; 
     } 
    } 

private: 
    int DoIt1() { 
     return 1; 
    } 

    int DoIt2() { 
     return 2; 
    } 

    // Typedef of a pointer to a class method. 
    typedef int (Test::*FuncPtr)(); 
    FuncPtr func; 
}; 

हालांकि, इससे पहले कि आप ऐसा करने का प्रयास में जाते हैं, प्रोफ़ाइल यदि आपका कोड पहले करें और देखें कि switch या if के माध्यम से शाखाओं में वास्तव में एक अड़चन है (यह नहीं हो सकता है!)। आधुनिक प्रोसेसर के पास बहुत ही प्रभावशाली प्रदर्शन विशेषताएं होती हैं, इसलिए कंपेलर बेहतर कोड उत्पन्न करने में सक्षम हो सकते हैं जो आपको लगता है। यह सुनिश्चित करने का एकमात्र तरीका है कि ब्रांचिंग वास्तव में आपके लिए उपयोग करने के लिए बहुत महंगा है, अपने कोड को प्रोफाइल करना है। (और "प्रोफाइलिंग" से मेरा मतलब है "अच्छी तरह से डिज़ाइन किए गए प्रयोग चलाएं", "परीक्षण के बिना एक झुकाव के साथ आना"।)

+0

'टाइपपीफ int (* FuncPtr)(); गलत है आपको 'typedef int (टेस्ट :: * FuncPtr)() लिखना होगा; ' – Nawaz

+0

@ नवाज: फिक्स्ड। यह बात बताने के लिए धन्यवाद। –

+0

अभी भी समस्या है। आपको '(यह -> * func)();' लिखना होगा, 'न केवल' func(); '। – Nawaz

1

आप अपना operator() एक इनलाइन फ़ंक्शन बना सकते हैं जो एक और पॉइंटर कहता है। अनुकूलक को अतिरिक्त संकेत बाहर लेना चाहिए।

1

एक समाधान @ इन सिलिको द्वारा प्रदान किया जाता है जो सी ++ 03 और सी ++ 11 दोनों में मान्य है। ; `... सही सिंटैक्स

std::function<int(Test*)> func; 

func = &Test::DoIt1; 

func(this); //this syntax is less cumbersome compared to C++03 solution 

A quick online full demo

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