2013-05-16 12 views
14

पर प्रतिनिधि मुझे अक्सर कई सदस्य चर के साथ कक्षाओं के लिए थकाऊ चाल रचनाकार लिखते हैं। वे कुछ ऐसी नज़र:डिफ़ॉल्ट चाल कन्स्ट्रक्टर

A(A && rhs) : 
    a(std::move(rhs.a)), 
    b(std::move(rhs.b)), 
    c(std::move(rhs.c)), 
    d(std::move(rhs.d)) { 
    some_extra_work(); 
} 

है यही कारण है, वे डिफ़ॉल्ट चाल निर्माता के साथ जुड़े कार्यों के सभी करते हैं, तो कुछ सांसारिक अतिरिक्त कार्य peform। आदर्श रूप में मैं डिफ़ॉल्ट चालक कन्स्ट्रक्टर को प्रतिनिधि दूंगा और फिर अतिरिक्त कार्य करता हूं, हालांकि मेरे स्वयं के चालक कन्स्ट्रक्टर को परिभाषित करने का कार्य डिफ़ॉल्ट कार्यान्वयन को परिभाषित होने से रोकता है, जिसका अर्थ है कि प्रतिनिधि को कुछ भी नहीं है।

क्या इस विरोधी-पैटर्न को पाने के लिए कोई अच्छा तरीका है?

+6

मुश्किल ऐसी अमूर्त स्तर पर कहने के लिए उपयोग करें, लेकिन शायद आप दो वर्गों में 'अलग कर सकता A' और डाल दूसरे में एक? एक में सभी डिफॉल्ट कन्स्ट्रक्टर होंगे और दूसरा 'some_extra_work' करेगा। * शून्य * के नियम की जांच करें। – zch

+0

यह सुनिश्चित नहीं है कि यह लागू है, लेकिन कुछ 'ए (ए && rhs, int): ए (rhs) {} 'काम नहीं करेगा? – Damon

+3

एक डिफ़ॉल्ट चालक कन्स्ट्रक्टर वाला इंटरमीडिएट बेस क्लास मदद कर सकता है। –

उत्तर

3

अद्यतन: इस उत्तर के पहले भाग को अनदेखा करें और अंत तक छोड़ें जिसमें एक बेहतर समाधान है।

एक नए प्रकार में

लपेटें अतिरिक्त काम और यह से विरासत:

class A; 

struct EW 
{ 
    EW(EW&&); 
}; 

class A : private EW 
{ 
    friend class EW; 
public: 
    A(A&&) = default; 
}; 

EW::EW(EW&&) { A* self = static_cast<A*>(this); self->some_extra_work(); } 

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

यह अगर some_extra_work() है काम नहीं करेगा के बाद सदस्यों प्रारंभ कर रहे हैं क्योंकि आधार वर्ग पहले प्रारंभ कर रहे हैं किया जाना चाहिए।

वैकल्पिक रूप से यदि अतिरिक्त कार्य वास्तव में उस रावल्यू ऑब्जेक्ट पर चल रहा है जिसे आप आगे बढ़ रहे हैं, तो आपको सदस्यों को ऐसे प्रकारों में लपेटना चाहिए जो उस स्थान से स्वचालित रूप से कार्य करते हैं, उदा। मेरी tidy_ptr प्रकार है, जो मैं लागू करने के लिए Rule of Zero

class A 
{ 
    tidy_ptr<D> d; 
public: 
    A() = default; 
    A(const A&) = default; 
    A(A&& r) = default; // Postcondition: r.d == nullptr 
}; 
+0

मुझे आश्चर्य है, क्या बेस-क्लास मूव सीटीओआर * पहले * सदस्य कदम ctors से पहले नहीं आ गया है? – Xeo

+0

यह हां है, इसलिए काम नहीं करेगा यदि अतिरिक्त कार्य अन्य सदस्यों पर निर्भर करता है। जब मैंने लिखा कि मैंने ओपी की टिप्पणी नहीं पढ़ी है, "मेरे लिए कुछ_extra_work() का क्लासिक उदाहरण है 'rhs.d = 0;' " –

+0

... उत्तर का दूसरा भाग उस मामले में काम करता है हालांकि –

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