2012-06-20 18 views
13

ऐसा लगता है कि std::cout तरह सदस्य समारोह का पता मुद्रित नहीं कर सकते, उदाहरण के लिए में सदस्य समारोह का पता मुद्रित करने के लिए:कैसे सी ++

#include <iostream> 

using std::cout; 
using std::endl; 

class TestClass 
{ 
    void MyFunc(void); 

public: 
    void PrintMyFuncAddress(void); 
}; 

void TestClass::MyFunc(void) 
{ 
    return; 
} 

void TestClass::PrintMyFuncAddress(void) 
{ 
    printf("%p\n", &TestClass::MyFunc); 
    cout << &TestClass::MyFunc << endl; 
} 

int main(void) 
{ 
    TestClass a; 

    a.PrintMyFuncAddress(); 

    return EXIT_SUCCESS; 
} 

परिणाम कुछ इस तरह है:

003111DB 
1 

मैं कैसे कर सकता है std::cout का उपयोग कर MyFunc का पता प्रिंट करें?

उत्तर

16

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

सामान्यतः, मुझे लगता है कि इसका मतलब है कि अनिश्चित व्यवहार का आह्वान किए बिना सदस्य कार्यों के पते मुद्रित करना असंभव है। इस प्रभाव को प्राप्त करने के लिए आपको शायद कुछ कंपाइलर-विशिष्ट चाल का उपयोग करना होगा।

आशा है कि इससे मदद मिलती है!

+0

आकार पर कुछ दिलचस्प आंकड़े और संकेत करने वाली सदस्य कार्यों विभिन्न में के कार्यान्वयन के लिए:

template<typename R, typename T, typename... Args> std::string to_string(R (T::*func)(Args...)) { union PtrUnion { R(T::*f)(Args...); std::array<unsigned char, sizeof(func)> buf; }; PtrUnion u; u.f = func; std::ostringstream os; os << std::hex << std::setfill('0'); for (auto c : u.buf) os << std::setw(2) << (unsigned)c; return os.str(); } 

आप इसे इस तरह से उपयोग कर सकते हैं कंपाइलर्स, [इस आलेख] के नीचे चार्ट देखें (http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible)। हालांकि, चूंकि वह लेख कुछ हद तक दिनांकित है (2005 में लिखा गया है), संख्याएं अब सटीक नहीं हैं, लेकिन वे एक मोटा विचार देते हैं। –

4

एक तरीका यह है कि ऐसा करने के लिए है (मुझे यकीन है कि यह पोर्टेबल है नहीं कर रहा हूँ):

void TestClass::PrintMyFuncAddress(void) 
{ 
    void (TestClass::* ptrtofn)() = &TestClass::MyFunc; 
    cout << (void*&)ptrtofn<< endl; 
} 

काम कर उदाहरण: http://ideone.com/1SmjW

+3

वह कार्यक्रम बहुत कम दिखाता है। वह सी-स्टाइल कास्ट एक 'reinterpret_cast' है जो आम तौर पर स्मृति प्रकार के रूप में स्मृति को दोहराता है। इस मामले में, यह सूचकांक में संग्रहीत पहले 'आकार (शून्य *) 'बाइट्स का उपयोग करेगा, जैसे कि यह' शून्य * 'था, लेकिन यदि आप दोनों प्रकार के आकारों की जांच करते हैं तो आप देखेंगे कि वे भिन्न हैं (सूचक सदस्य के लिए बड़ा है)। –

+0

@ डेविडरोड्रिगुएज़-ड्राईबीस: लेकिन इसे (संभवतः) printf() के "% p" के समान मान मुद्रित करना चाहिए। वे दोनों गलत हैं (माना जाता है कि सदस्य पॉइंटर्स सामान्य पॉइंटर्स (आमतौर पर सच) से बड़े होते हैं)। –

13

मैं अन्य उत्तर में जोड़ने के लिए, यही कारण है चाहता हूँ कि आपको किसी पते के बजाय '1' मुद्रित किया जा रहा है, यह है कि, किसी कारण से, कंपाइलर आपके फ़ंक्शन पॉइंटर को बुलियन में जोड़ रहा है, ताकि आप वास्तव में ostream& operator<< (bool val);

फ़ंक्शन होने से संबंधित न हों एक सदस्य एफ अभिषेक हुआ। सदस्य कार्यों के लिए

(ImplicitCastExpr 0x3861dc0 <col:13, col:25> '_Bool' <MemberPointerToBoolean> 
    (UnaryOperator 0x3861940 <col:13, col:25> 'void (class TestClass::*)(void)' prefix '&' 
     (DeclRefExpr 0x38618d0 <col:14, col:25> 'void (void)' CXXMethod 0x3861500 'MyFunc' 'void (void)'))))) 
+0

लाइन संख्या बदल दी गई है। –

+1

सिंटैक्स डंप विकल्प को इंगित करने के लिए धन्यवाद। – fduff

+0

आपका स्वागत है ... ;-) –

1

प्वाइंटर स्मृति की जरूरत है, भी:

आप ++ बजना के साथ इस प्रकार की जानकारी -cc1 -ast-डंप को उजागर कर सकते हैं। उनके पास आकार भी है। तो कैसे सूचक की स्मृति बाहर प्रिंट करने के बारे:

class TestClass 
{ 
    void foo(); 
}; 

... 

std::cout << to_string(&TestClass::foo) << std::endl;