2010-12-08 15 views
14

मेरे पास एक बेस क्लास है जो मूल रूप से एक कक्षा को मनमाने ढंग से विंडोज हैंडल (उदाहरण के लिए, एचडब्ल्यूएनडी, एचएफओटी) में जोड़ने के लिए लपेटती है, और संलग्न/अलग करने और नष्ट करने के लिए पॉलिसी क्लास का उपयोग करती है:कन्स्ट्रक्टर कॉलिंग बेस-क्लास मूव कन्स्ट्रक्टर

// class SmartHandle 
template<typename THANDLE, class TWRAPPER, class TPOLICY> 
class SmartHandle : boost::noncopyable 
{ 
private: 
    TPOLICY* m_pPolicy; // Policy 
    bool m_bIsTemporary; // Is this a temporary window? 

    SmartHandle(); // no default ctor 
    SmartHandle(const SmartHandle<THANDLE, TWRAPPER, TPOLICY>&); // no cctor 
protected: 
    THANDLE m_hHandle; // Handle to the underlying window 

    TPOLICY& policy() {return(*m_pPolicy);}; 

    // ctor that attaches but is temporary 
    SmartHandle(const THANDLE& _handle, bool _temporary) : m_hHandle(_handle) 
                 , m_bIsTemporary(_temporary) 
    { 
     m_pPolicy = new TPOLICY(reinterpret_cast<TWRAPPER&>(*this)); 
     if(_handle) 
      m_pPolicy->attach(_handle); 
    }; // eo ctor 

    // move ctor 
    SmartHandle(SmartHandle<THANDLE, TWRAPPER, TPOLICY>&& _rhs) : m_hHandle(_rhs.m_hHandle) 
                     , m_bIsTemporary(_rhs.m_bIsTemporary) 
    { 
     m_pPolicy = new TPOLICY(reinterpret_cast<TWRAPPER&>(*this)); 
     m_pPolicy->attach(m_hHandle); 
     const_cast<SmartHandle&>(_rhs).m_hHandle = NULL; 
    }; // eo mtor 

    // dtor 
    virtual ~SmartHandle() 
    { 
     if(m_hHandle) 
     { 
      m_pPolicy->detach(m_hHandle); 
      if(!m_bIsTemporary) 
       m_pPolicy->destroy(m_hHandle); 
      m_hHandle = NULL; 
     }; 
     delete(m_pPolicy); 
     m_pPolicy = NULL; 
    }; // eo dtor 

ध्यान दें कि मैं प्रतिलिपि निर्माता निजी (कोई कार्यान्वयन के साथ) घोषित कर दिया है के रूप में मैं वर्ग कॉपी किया जा नहीं करना चाहते हैं, लेकिन एक कदम अनुमति दी है।

मेरे Window वर्ग इस से निकला है:

class GALLOW_API Window : SmartHandle<HWND, Window, detail::_hWndPolicy> 
    { 
    friend class Application; 
    private: 
     static LRESULT CALLBACK wndProc(HWND _hWnd, UINT _message, WPARAM _wParam, LPARAM _lParam); 

     // no copy/default ctor 
     Window(); 
     Window(const Window&); 
    protected: 

    public: 
     static const String ClassName; 
     Window(const HWND& _hWnd); 
     Window(const WindowCreateInfo& _createInfo); 
     Window(Window&& _rhs); 
     virtual ~Window(); 
    }; // eo class Window 

एक बार फिर, प्रतिलिपि डिफ़ॉल्ट/कॉपी ctors। इस कदम निर्माता के कार्यान्वयन है:

Window::Window(Window&& _rhs) : SmartHandle(_rhs) 
    { 
    }; // eo mtor 

हालांकि, संकलन के दौरान मैं इस कदम निर्माता कार्यान्वयन की पहली पंक्ति पर निम्न त्रुटि मिलती है:

1>c:\\documents\visual studio 2010\projects\gallow\gallow\window.cpp(81): error C2248: 'gallow::SmartHandle<THANDLE,TWRAPPER,TPOLICY>::SmartHandle' : cannot access private member declared in class 'gallow::SmartHandle<THANDLE,TWRAPPER,TPOLICY>' 

तो, ऐसा लगता है जैसे कि वह कोशिश कर रहा है चालक कन्स्ट्रक्टर के बजाय कॉपी कन्स्ट्रक्टर (जिसे मैंने निजी घोषित किया है) को कॉल करने के लिए। क्या मैं कुछ याद कर रहा हूं?

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

संपादित करें: संशोधित mtor तो यह गैर-स्थिर था, त्रुटि बनी हुई थी। EDIT2: मैं विजुअल सी ++ 2010 का उपयोग कर रहा हूं।

+2

डुप्लिकेट? http://stackoverflow.com/questions/4086800/move-constructor-on-derived-object –

+0

एरिक, धन्यवाद, मैंने इसे पकड़ नहीं लिया। हां, जिसने पूरी तरह से समस्या हल की, इच्छा है कि मैं आपका जवाब स्वीकार कर सकूं :) –

उत्तर

4

एक चालक कन्स्ट्रक्टर T(T&&) होना चाहिए, T(const T&&) नहीं।

+0

धन्यवाद, मैंने इसे संशोधित किया है, लेकिन यह मुझे प्राप्त होने वाली त्रुटि से असंबंधित है। –

10

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

Window::Window(Window&& _rhs) : SmartHandle(std::move(_rhs)) 
{ 
} 

कारण एक तर्क एक rvalue के रूप में व्यवहार नहीं कर रहा है कि यह दो बार इस्तेमाल किया जा सकता है और आम तौर चलती मूल्य बदलता है इसलिए आप जानते हुए भी कि इस चर से ले जाया जाता है के बारे में स्पष्ट होना जरूरी है।

उदा।

void f(string&& first, string&& second) 
{ 
    string local = first; 
    cout << first; // I would be surprised if this is different from `local` 

    local = std::move(second); 
    // If I'm surprised after explicitly moving from second it's my problem 
} 

यह मामलों में move बजाय forward उपयोग करने के लिए जब आप ले जाना चाहते के बाद से एक) यह स्पष्ट है और ख) आप forward जो वर्बोज़ और त्रुटि प्रवण है का प्रकार निर्दिष्ट करने की जरूरत है बेहतर है।

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