2013-03-12 15 views
13

ले जाएं मैं कन्स्ट्रक्टर और असाइनमेंट ओप को सी ++ 11 में काम करने के तरीके को समझने की कोशिश कर रहा हूं लेकिन मुझे मूल कक्षाओं में प्रतिनिधि के साथ समस्याएं आ रही हैं।कन्स्ट्रक्टर और विरासत

कोड:

class T0 
{ 
public: 
    T0() { puts("ctor 0"); } 
    ~T0() { puts("dtor 0"); } 
    T0(T0 const&) { puts("copy 0"); } 
    T0(T0&&) { puts("move 0"); } 
    T0& operator=(T0 const&) { puts("assign 0"); return *this; } 
    T0& operator=(T0&&) { puts("move assign 0"); return *this; } 
}; 

class T : public T0 
{ 
public: 
    T(): T0() { puts("ctor"); } 
    ~T() { puts("dtor"); } 
    T(T const& o): T0(o) { puts("copy"); } 
    T(T&& o): T0(o) { puts("move"); } 
    T& operator=(T const& o) { puts("assign"); return static_cast<T&>(T0::operator=(o)); } 
    T& operator=(T&& o) { puts("move assign"); return static_cast<T&>(T0::operator=(o)); } 
}; 

int main() 
{ 
    T t = std::move(T()); 
    return 0; 
} 

हालांकि, जब मैं संकलन और VS2012 के तहत चलाने के लिए, उत्पादन इंगित करता है कि T0 सदस्यों की lvalue संस्करणों कहा जाता है:

ctor 0 
ctor 
copy 0 <-- 
move <-- 
dtor 
dtor 0 
dtor 
dtor 0 

एक ऐसी ही स्थिति (साथ थोड़ा अलग परीक्षण केस) चाल असाइनमेंट के साथ होता है - टी के चाल असाइनमेंट ऑपरेटर टी 0 के "सामान्य" असाइनमेंट ऑपरेटर को कॉल करता है।

मैं क्या गलत कर रहा हूं?

उत्तर

16

अधिक में से एक पैरामीटर के रूप में रावल संदर्भों को ले जाने वाले कार्यों के बारे में भ्रमित चीजें यह है कि आंतरिक रूप से वे अपने मानकों को लालसा के रूप में मानते हैं। यह आपको पैरामीटर को आगे बढ़ाने से पहले रोकने के लिए है, लेकिन इसमें कुछ उपयोग किया जाता है। वास्तव में पैरामीटर को स्थानांतरित करने के लिए, आपको std :: move (या std :: आगे) पर कॉल करना होगा। तो अगर आप अपनी चाल निर्माता परिभाषित करने की आवश्यकता के रूप में:

T(T&& o): T0(std::move(o)) { puts("move"); } 

और के रूप में अपनी चाल असाइनमेंट ऑपरेटर:

T& operator=(T&& o) { puts("move assign"); return static_cast<T&>(T0::operator=(std::move(o))); } 
5

आप केवल कभी lvalues ​​के साथ अपने आधार वर्ग के सामान कॉल कर रहे हैं:

void foo(int&){} // A 
void foo(int&&){} // B 

void example(int&& x) 
{ 
    // while the caller had to use an rvalue expression to pass a value for x, 
    // since x now has a name in here it's an lvalue: 
    foo(x); // calls variant A 
} 

example(std::move(myinteger)); // rvalue for us, lvalue for example 

है यही कारण है, आप की जरूरत:

T(T&& o): 
T0(std::move(o)) // rvalue derived converts to rvalue base 
{ 
    puts("move"); 
} 

और:

T& operator=(T&& o) 
{ 
    puts("move assign"); 

    T0::operator=(std::move(o))); 

    return *this; 
} 
संबंधित मुद्दे