6

मैं जीसीसी 4.5 का उपयोग कर रहा हूं और बहुत ही असाधारण व्यवहार देखता हूं। मैं सोच रहा हूं कि इस ऑपरेटर के साथ कुछ ऐसा है जो मैं पूरी तरह समझ नहीं पा रहा हूं। मैंने सोचा कि मैं सी ++ में कुशल था। मेरे पास एक कार्यान्वित कास्ट ऑपरेटर operator HWND ... के साथ विंडोज HWND ऑब्जेक्ट्स के लिए एक पतली सी ++ रैपर क्लास Wnd है।सशर्त ऑपरेटर की सीमाएं ?:

यदि मैं यह (दिए गए इनपुट Wnd *p और एक नमूना समारोह SetParent(HWND)) तरह सशर्त ऑपरेटर का उपयोग करें:।।

SetParent((p!=NULL) ? (HWND)(*p) : NULL) 

माता पिता ठीक से NULL या p के आधार पर सेट है यह मैं क्या उम्मीद करेंगे है लेकिन अगर आलसी और लिखने होने की हिम्मत:। GDB चलाने के बाद

SetParent(p ? *p : NULL) 

चीजें बिगड़ जाना मुझे लगता है कि नाशक vari पर कहा जाता है पर कॉल करने के बाद सक्षम p। कोई विचार क्या हो रहा है?

संपादित यहाँ मेरी WND वर्ग है:

class Wnd{ 
     HWND m_hwnd;  ///< the actual handle 
     WndFake *fake;  ///< store state here if we do not have a handle 
    public: 
     virtual ~Wnd(); 
     //contructor s 
     Wnd(HWND wnd=NULL):m_hwnd(wnd),fake(NULL){} 
     Wnd(DWORD sty,const jchar *title,const RECT &sz); 
     operator HWND(){return m_hwnd;} 
     operator HWND() const {return m_hwnd;} 
    } 
+9

आप शायद अपना पूरा 'Wnd' वर्ग परिभाषा दिखाने की जरूरत जा रहे हैं। –

+0

@bacchus, ध्यान दें कि आपके '(HWND))' संपादित गलत था: डी हालांकि बेहतर रिक्ति अच्छा है ... – sarnold

+0

@sarnold अतिरिक्त ब्रैकेट सजा से है। मैंने यह खो दिया। चेतावनी के लिए धन्यवाद;) – bacchus

उत्तर

4

मुझे संदेह है कि आपके डब्ल्यूडब्ल्यू में गैर-स्पष्ट रूपांतरण कन्स्ट्रक्टर भी है जो एचडब्ल्यूएनडी या यहां तक ​​कि int भी लेता है? यदि ऐसा है तो इसे स्पष्ट करें।

आपके WND में प्रतिलिपि बनाने वाले निर्माता और ऑपरेटर = घोषित नहीं हैं? इन निजी घोषित करें और उन्हें परिभाषित न करें।

operator HWND को भी हटाएं और अपने WND में सदस्य फ़ंक्शन HWND hwnd() const; जोड़ें।

Setparent(p ? p->hwnd() : NULL); 

मुझे विश्वास है कि जब इन mods किया जाता है कि आपको पता चल जाएगा कि आपके WND साथ कुछ गड़बड़ है: तो फिर कोड की तरह पठनीय दिखेगा।

समस्या स्वयं प्रकट होती है क्योंकि इन दोनों के किनारों पर संचालित होता है: में:: एक ही प्रकार का होना चाहिए ताकि नल (0) किसी भी तरह से डब्ल्यूडब्ल्यू में परिवर्तित हो सके। तो * पी की अस्थायी प्रति के वापसी मूल्य के रूप में बनाई गई है: तो ऑपरेटर एचडब्ल्यूएनडी इसे बुलाया जाता है।

+0

+1 मुझे लगता है कि 'HWND' से' WND' तक अंतर्निहित रूपांतरण को हटाने से चाल चलनी चाहिए, क्योंकि यह 'NULL' से' WND' तक रूपांतरण अक्षम करता है और संकलक को विपरीत दिशा में रूपांतरित करने के लिए मजबूर किया जाएगा। किसी भी दर पर आप पूरी तरह से सही हैं कि निहित रूपांतरणों को हटाने से कोड अधिक पठनीय और रखरखाव योग्य हो जाएगा। –

3

नाशक चर पी पर या कुछ अस्थायी चर पी की एक प्रति है कि पर बुलाया है?

अपने पहले उदाहरण में आप *p को HWND में परिवर्तित करने के लिए सी-स्टाइल कास्ट का उपयोग कर रहे हैं। दूसरे में, आप संकलक को रूपांतरण करने दे रहे हैं, और इसमें *p की प्रतिलिपि बनाना शामिल हो सकता है।

2

?: ऑपरेटर के ऑपरेटरों को सामान्य प्रकार में लाया जाना चाहिए, जिसका परिणाम परिणामस्वरूप उपयोग किया जाएगा। जब आप

SetParent(p != NULL ? (HWND) *p : NULL); 

का उपयोग आप अनिवार्य रूप से मैन्युअल रूप से आम प्रकार चुनते हैं, तो स्थिति मजबूर जब संकलक है HWND किया जाना है। अर्थात।इसके बाद के संस्करण संस्करण

SetParent(p != NULL ? (HWND) *p : (HWND) NULL); 

के बराबर है लेकिन जब आप

SetParent(p != NULL ? *p : NULL); 

भाषा काम के नियमों को अलग ढंग से करते हैं, संकलक अलग ढंग से आम प्रकार तय करेगा। इसमें सामान्य प्रकार HWND नहीं है, लेकिन आपका Wnd है। दोनों ऑपरेंड Wnd में बदल रही हैं और बाद संस्करण

SetParent(p != NULL ? *p : Wnd(NULL)); 

यानी के रूप में व्याख्या की है जब p रिक्त है संकलक एक अस्थायी वस्तु Wnd(NULL) (रूपांतरण निर्माता आपके द्वारा दी गई उपयोग करते हुए) का निर्माण करती है और परिणाम के रूप में वापस करती है। इसके अलावा, संकलक संभवतः वास्तविक शाखा में एक अस्थायी वस्तु का निर्माण करेगा (कॉपी कन्स्ट्रक्टर का उपयोग करके)। उसके एवज में अस्थायी वस्तु तो HWND प्रकार में बदल जाती है (के बाद से है कि क्या SetParent की आवश्यकता है), इसलिए पूरी बात व्याख्या की है के रूप में

SetParent((HWND) (p != NULL ? Wnd(*p) : Wnd(NULL))); 

अस्थायी वस्तु तो SetParent करने के लिए कॉल के तुरंत बाद नष्ट हो जाता है। यह वह विनाश है जिसे आपने देखा, सिवाय इसके कि आपने इसे p के विनाश के रूप में गलत तरीके से व्याख्या की है।

कारण संकलक यह तरीका अपना सकते हैं क्योंकि आपकी रूपांतरण निर्माता explicit घोषित नहीं किया जाता है। आप रूपांतरण निर्माता की घोषणा तो explicit

class Wnd { 
    ... 
    explicit Wnd(HWND wnd=NULL) : m_hwnd(wnd), fake(NULL) {} 
    ... 
}; 

संकलक अब परोक्ष Wnd को NULL कन्वर्ट करने के लिए उपयोग करने के लिए सक्षम हो जाएगा। उस मामले में संकलक और कोई चारा नहीं रह जाएगा, लेकिन एक आम प्रकार के बजाय

SetParent(p != NULL ? (HWND) *p : (HWND) NULL); 

, जैसा कि आपने यह करना चाहता था के रूप में HWND उपयोग करने के लिए।

पीएस आप पहले से ही अपनी कक्षा में operator HWND() const है, वहाँ समान और नहीं स्थिरांक संस्करण operator HWND() को लागू करने का कोई मतलब नहीं है।

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