दिलचस्प पोस्ट
कैसे एक क्वेरी स्ट्रिंग के भीतर एक सरणी को पारित करने के लिए? जावास्क्रिप्ट में डिफर्ड, वादा और भविष्य के बीच अंतर क्या हैं? कक्षा के लिए कंपाइलर द्वारा बनाए गए सभी सदस्य-फ़ंक्शन क्या हैं? क्या ऐसा हर समय होता है? चयन सूची में छवियां कैसे जोड़ें फ़ंक्शन के कॉलबैक के रूप में उदाहरण विधि का उपयोग कैसे करें, जो केवल फ़ैन्क या शाब्दिक बंद होता है node.js, SSL के साथ socket.io जावा के लिए आराम ग्राहकों? Scanf के नुकसान .NET में प्रारूप स्ट्रिंग में ब्रेसिज़ (घुंघराले ब्रैकेट) से बचने के लिए कैसे करें अनुक्रमितों का सी ++ सॉर्टिंग और रखे जाने का तरीका पीएचपी का उपयोग कर सर्वर पर छवि अपलोड करते समय डेटाबेस में फ़ाइल नाम को कैसे स्टोर करना है? Document.getElementById का उपयोग कर iframe के अंदर तत्व कैसे लें IIS लॉग्स कहां मिल सकता है? एचटीटीपी एचटीटीपी के लिए एचटीएसीएक्स का इस्तेमाल कर रहा है चयनित रेडियो पर jQuery विकल्प चुनें विकल्प (सभी ब्राउज़रों के लिए समर्थन की आवश्यकता है)

Cout के साथ फ़ंक्शन पॉइंटर्स कैसे मुद्रित करें?

मैं cout का उपयोग करते हुए फ़ंक्शन पॉइंटर को प्रिंट करना चाहता हूं, और पाया कि यह काम नहीं करता। लेकिन फ़ंक्शन पॉइंटर को (शून्य *) में परिवर्तित करने के बाद यह काम करता है, इसलिए% p के साथ printf करता है, जैसे कि

#include <iostream> using namespace std; int foo() {return 0;} int main() { int (*pf)(); pf = foo; cout << "cout << pf is " << pf << endl; cout << "cout << (void *)pf is " << (void *)pf << endl; printf("printf(\"%%p\", pf) is %p\n", pf); return 0; } 

मैंने इसे जी ++ के साथ संकलित किया और इसका परिणाम मिला:

cout << पीएफ 1 है
cout << (शून्य *) पीएफ 0x100000b0c है
printf ("% p", पीएफ) 0x100000b0c है

तो क्या cout प्रकार int (*) () के साथ होता है? मुझे बताया गया कि फ़ंक्शन पॉइंटर को बूल के रूप में माना जाता है, क्या यह सच है? और cout प्रकार (शून्य *) के साथ क्या करता है?

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

संपादित करें: किसी भी तरह, हम फ़ंक्शन पॉइंटर की सामग्री को इसे (शून्य *) में कनवर्ट करके और cout का उपयोग करके इसे प्रिंट कर सकते हैं। लेकिन यह सदस्य फ़ंक्शन पॉइंटर्स के लिए काम नहीं करता है और कंपाइलर गैरकानूनी रूपांतरण के बारे में शिकायत करता है। मुझे पता है कि सदस्य फ़ंक्शन पॉइंटर्स साधारण पॉइंटर्स के अलावा एक जटिल संरचना है, लेकिन हम एक सदस्य फ़ंक्शन पॉइंटर्स की सामग्री कैसे देख सकते हैं?

वेब के समाधान से एकत्रित समाधान "Cout के साथ फ़ंक्शन पॉइंटर्स कैसे मुद्रित करें?"

वास्तव में << ऑपरेटर का एक अधिभार है जो कुछ ऐसा दिखता है:

 ostream & operator <<( ostream &, const void * ); 

जो आपको उम्मीद करता है – हेक्स में आउटपुट। फ़ंक्शन पॉइंटर के लिए ऐसा कोई मानक लाइब्रेरी अधिभार नहीं हो सकता, क्योंकि उनमें से कई प्रकार के अनंत संख्याएं हैं तो सूचक एक अन्य प्रकार में परिवर्तित हो जाता है, जो इस मामले में एक बाउल लगता है – मैं इसके लिए नियमों को याद नहीं रख सकता

संपादित करें: सी ++ मानक निर्दिष्ट करता है:

4.12 बूलियन रूपांतरण

1 सदस्य प्रकार के अंकगणितीय, गणण, संकेतक, या सूचक की संख्या में टाइप बूल के एक रेंवेल में परिवर्तित किया जा सकता है।

फ़ंक्शन पॉइंटर के लिए निर्दिष्ट यह एकमात्र रूपांतरण है

आपके संपादन के बारे में, आप इसे unsigned char संकेतक के माध्यम से एक्सेस कर सकते हैं। सदस्य कार्यों में पॉइंटर्स के लिए एक उदाहरण:

 #include <iostream> #include <iomanip> struct foo { virtual void bar(){} }; struct foo2 { }; struct foo3 : foo2, foo { virtual void bar(){} }; int main() { void (foo3::*p)() = &foo::bar; unsigned char const * first = reinterpret_cast<unsigned char *>(&p); unsigned char const * last = reinterpret_cast<unsigned char *>(&p + 1); for (; first != last; ++first) { std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*first << ' '; } std::cout << std::endl; } 

आप उस फंक्शन के मशीन कोड के पहले निर्देश के पते के रूप में फ़ंक्शन पॉइंटर के बारे में सोच सकते हैं। किसी भी सूचक को bool रूप में माना जा सकता है: 0 गलत है और बाकी सब सच है। जैसा कि आपने देखा, जब डाली void * को डाली जाती है और स्ट्रीम प्रविष्टि ऑपरेटर ( << ) पर तर्क के रूप में दिया जाता है, तो पता प्रिंट होता है। (सख्ती से देखा गया, void * से एक पॉइंटर-टू-फ़ंक्शन कास्टिंग करना अनिर्धारित है।)

कलाकारों के बिना, कहानी थोड़ा जटिल है ओवरलोड किए गए फ़ंक्शंस ("ओवरलोड रिज़ॉल्यूशन") के मिलान के लिए, सी ++ कंपाइलर उम्मीदवार कार्यों का एक समूह एकत्र करता है और इन उम्मीदवारों से यदि आवश्यक हो तो अंतर्निहित रूपांतरणों का उपयोग करके "सर्वश्रेष्ठ व्यवहार्य" का चयन करता है। शिकन मिलान नियमों का आंशिक क्रम है, इसलिए कई सर्वोत्तम-व्यवहार्य मैचों में अस्पष्टता त्रुटि उत्पन्न होती है।

वरीयता के क्रम में, मानक रूपांतरण (और निश्चित रूप से उपयोगकर्ता-परिभाषित और एलीपिस रूपांतरण भी, विस्तृत नहीं हैं)

  • सटीक मिलान ( यानी , कोई रूपांतरण आवश्यक नहीं)
  • पदोन्नति ( जैसे , float लिए int )
  • अन्य रूपांतरण

अंतिम श्रेणी में बूलियन रूपांतरण शामिल हैं, और किसी भी सूचक प्रकार को bool : 0 (या NULL ) में बदला जा सकता है false और बाकी सब true । बाद में 1 रूप में प्रदर्शित होता है जब स्ट्रीम प्रविष्टि ऑपरेटर को पास किया जाता है।

इसके बजाय 0 प्राप्त करने के लिए, अपनी प्रारंभिकता को बदलने के लिए

 pf = 0; 

याद रखें कि एक शून्य-मूल्यवान निरंतर अभिव्यक्ति के साथ एक सूचक को प्रारंभ करने से रिक्त सूचक निकल जाता है

सीओएट को प्रिंट करने के लिए पॉइंटर्स को कास्ट करने के लिए (void*) का उपयोग सी ++ में करने के लिए सही चीज़ (टीएम) है, यदि आप उनके मूल्यों को देखना चाहते हैं

आपके विशिष्ट प्रश्न के बारे में,

हम सदस्य समारोह संकेतक की सामग्री कैसे देख सकते हैं?

इसका जवाब है, बुल में परिवर्तित करने के अलावा, यह व्यक्त करने के लिए कि यह कुछ इंगित करता है या नहीं, आप 'प्रेक्षक' सदस्य कार्य संकेतक नहीं देख सकते हैं। कम से कम एक अनुरुप तरीके से नहीं। इसका कारण यह है कि मानक स्पष्ट रूप से इसे अस्वीकार करता है:

4.12 फुटनोट 57:

57) पॉइंटर्स को पॉइंटेटर से ऑब्जेक्ट्स (पॉइंटर से लेकर पॉइन्टर तक बेस तक) (4.10, क्लॉज़ 10) के लिए पॉइंटर्स के रूपांतरण के लिए नियम (सूचक से लेकर सूचक के सदस्य तक) । प्रकार सुरक्षा सुनिश्चित करने के लिए यह उलटा जरूरी है ध्यान दें कि सदस्य के लिए एक सूचक ऑब्जेक्ट या कार्य करने के लिए एक सूचक नहीं है और ऐसे पॉइंटर्स के रूपांतरणों के नियम सदस्यों को पॉइंटर्स पर लागू नहीं होते हैं। विशेष रूप से, सदस्य के लिए एक सूचक को शून्य * में परिवर्तित नहीं किया जा सकता है

उदाहरण के लिए, यहां नमूना कोड है:

 #include <cstdlib> #include <vector> #include <algorithm> #include <string> #include <iostream> using namespace std; class Gizmo { public: void DoTheThing() { return; }; private: int foo_; }; int main() { void(Gizmo::*fn)(void) = &Gizmo::DoTheThing; Gizmo g; (g.*fn)(); // once you have the function pointer, you can call the function this way bool b = fn; // void* v = (void*)fn; // standard explicitly disallows this conversion cout << hex << fn; return 0; } 

मुझे ध्यान दें कि मेरा डिबगर (एमएसवी 9 9) मुझे रनटाइम में सदस्य फ़ंक्शन का वास्तविक भौतिक पता बता सकता है, इसलिए मुझे पता है कि उस पते को वास्तव में लाने का कोई तरीका होना चाहिए। लेकिन मुझे यकीन है कि यह गैर-कन्फॉर्मेंट, गैर-पोर्टेबल है और शायद मशीन कोड शामिल है। अगर मुझे उस सड़क के नीचे जाना पड़ता था, तो मैं फ़ंक्शन पॉइंटर (उदा। &fn ) के पते को ले कर शुरू कर देता हूं, जो कि * शून्य से निकलता है, और वहां से जाता हूं। इससे आपको संकेतकों के आकार (विभिन्न प्लेटफार्मों पर अलग) के बारे में पता होना चाहिए।

लेकिन मैं पूछूंगा, जब तक आप सदस्य-फ़ंक्शन पॉइंटर को बूल में परिवर्तित कर सकते हैं और पॉइंटर के अस्तित्व का मूल्यांकन कर सकते हैं, असली कोड में आपको पते की आवश्यकता क्यों होगी?

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

 #include <cstdlib> #include <vector> #include <algorithm> #include <string> #include <iostream> using namespace std; class Gizmo { public: void DoTheThing() { return; }; **void DoTheOtherThing() { return; };** private: int foo_; }; int main() { void(Gizmo::*fn)(void) = &Gizmo::DoTheThing; Gizmo g; (g.*fn)(); // once you have the function pointer, you can call the function this way bool b = fn; // void* v = (void*)fn; // standard explicitly disallows this conversion cout << hex << fn; **void(Gizmo::*fnOther)(void) = &Gizmo::DoTheOtherThing; bool same = fnOther == fn; bool sameIsSame = fn == fn;** return 0; } 

सी ++ 11 में operator<< एक variadic टेम्पलेट ओवरलोड परिभाषित करके इस व्यवहार को संशोधित कर सकता है operator<< (चाहे वह सिफारिश है या नहीं एक और विषय है):

 #include<iostream> namespace function_display{ template<class Ret, class... Args> std::ostream& operator <<(std::ostream& os, Ret(*p)(Args...) ){ // star * is optional return os << "funptr " << (void*)p; } } // example code: void fun_void_void(){}; void fun_void_double(double d){}; double fun_double_double(double d){return d;} int main(){ using namespace function_display; // ampersands & are optional std::cout << "1. " << &fun_void_void << std::endl; // prints "1. funptr 0x40cb58" std::cout << "2. " << &fun_void_double << std::endl; // prints "2. funptr 0x40cb5e" std::cout << "3. " << &fun_double_double << std::endl; // prints "3. funptr 0x40cb69" }