पुन: प्रारंभ करने के लिए एक कन्स्ट्रक्टर को कॉल करना क्या इसके कन्स्ट्रक्टर का उपयोग करके कक्षा के किसी ऑब्जेक्ट को फिर से शुरू करना संभव है?ऑब्जेक्ट
ऑब्जेक्ट
उत्तर
की क्रमबद्ध करें। एक वर्ग एक को देखते हुए:
A a;
...
a = A();
पिछले बयान initialisation नहीं है, यह काम है, लेकिन यह शायद तुम क्या चाहते है।
+1 बेशक इसे एक पूर्ण, सही असाइनमेंट ऑपरेटर लिखने की भी आवश्यकता है। –
@ ग्रेग के लिए यह एक सही असाइनमेंट ऑपरेटर है, जो आवश्यक रूप से लिखना आवश्यक नहीं है - डिफ़ॉल्ट अक्सर पूरी तरह से ठीक होगा। –
यदि '''' को' नया 'कीवर्ड का उपयोग करके तत्काल किया गया तो क्या यह संसाधन रिसाव का कारण बन जाएगा? – davidhood2
नहीं, कन्स्ट्रक्टर केवल तभी बुलाए जाते हैं जब ऑब्जेक्ट पहली बार बनाया जाता है। इसके बजाय इसे करने के लिए एक नई विधि लिखें।
संपादित
मैं नियुक्ति नई स्वीकार नहीं करेगा, क्योंकि मैं काम के लिए एक पालतू जानवर रैप्टर प्राप्त करने के लिए नहीं करना चाहती।
See this comic, लेकिन हाथ पर विषय के बारे में सोच ...
लघु जवाब:
नहीं। यदि आपका वस्तु की अभिप्रेत व्यवहार का हिस्सा कई बार, इस लागू करने के लिए तो सबसे अच्छा तरीका प्रारंभ किया जा रहा है एक सुलभ प्रारंभ विधि के माध्यम से है। आपकी कक्षा का निर्माता बस इस विधि को स्थगित कर सकता है।
class C1 {
public:
C1(int p1, int p2) {
Init(p1,p2);
}
void Init(int p1, int p2) { ... }
};
Nitpicker कोने:
वहाँ कुछ अविश्वसनीय रूप से बुराई एक वस्तु के बाद C++ में एक निर्माता कॉल करने के लिए बनाई गई है रास्ता नहीं है? लगभग निश्चित रूप से, यह सब के बाद सी ++ है। लेकिन यह मूल रूप से बुराई है और इसका व्यवहार लगभग निश्चित रूप से मानक द्वारा परिभाषित नहीं किया गया है और इससे बचा जाना चाहिए।
यह संभव है, हालांकि यह एक बहुत बुरा विचार है। कारण यह है कि मौजूदा वस्तु पर विनाशकों को बुलाए बिना, आप संसाधनों को रिसाव करने जा रहे हैं।
उस प्रमुख चेतावनी के साथ, यदि आप इसे करने पर जोर देते हैं, तो आप प्लेसमेंट का उपयोग कर सकते हैं।
// Construct the class
CLASS cl(args);
// And reconstruct it...
new (&cl) CLASS(args);
आपको इसे किसी को सुझाव देने के लिए केवल -1 प्राप्त करना चाहिए: पी, लेकिन एक +1 हैक के लिए - यह नहीं पता था, इसलिए कुल –
में 0 0 'प्ले-> ~ क्लास();' प्लेसमेंट से पहले, जैसा कि मैंने जेरेड के जवाब पर कहा था। मुझे यकीन नहीं है कि यह परिभाषित है, कानूनी लगता है। – GManNickG
+1, केवल सही समाधान। बुराई नहीं, यह तरीका है कि यह कैसे किया जाता है। –
सचमुच? हां, प्लेसमेंट का उपयोग करके नया। लेकिन सबसे पहले आपको पहले निर्मित वस्तु को नष्ट करना होगा।
SomeClass object(1, 2, 3);
...
object.~SomeClass(); // destruct
new(&object) SomeClass(4, 5, 6); // reconstruct
...
// Final destruction will be done implicitly
हालांकि इसका मूल्य पूरी तरह से सैद्धांतिक से परे नहीं जाता है। अभ्यास में ऐसा मत करो। पूरी बात विवरण से परे बदसूरत है।
क्या आप समझा सकते हैं कि आप क्यों मानते हैं कि यह "विवरण से बदसूरत" है? ऐसा लगता है कि यह कोड डुप्लिकेशंस और बग्स से बचने में एक वैध उपयोग है जो एक 'स्पष्ट' विधि को एक निर्माता और विनाशक से अलग करता है। –
क्या बनाता है यह "बदसूरत" यह है कि 'ऑब्जेक्ट' पर विनाशक को बुलाए जाने के बाद, आपके पास एक अनियंत्रित स्टैक वैरिएबल है। इस बिंदु के बाद 'ऑब्जेक्ट' के साथ कुछ भी करने की कोशिश करना असुरक्षित है। यहां तक कि कोई तरीका नहीं है तकनीक कि ऑब्जेक्ट बाद में नष्ट कर दिया गया है। लेकिन एक बार पुनर्निर्माण के बाद, यह फिर से वैध है। मैं तब तक कहूंगा जब तक कि दो पंक्तियां पीछे-पीछे हों, यह सुरक्षित है। –
ईमानदारी से, मैं इसे किसी भी प्रकार के वर्ड टेम्पलेट फ़ंक्शन या यहां तक कि केवल एक मैक्रो में डाल सकता हूं, यह स्पष्ट करने के लिए कि क्या हो रहा है और दो कथनों के बीच कोड को गलती से डालने से रोकने के लिए। – LivePastTheEnd
आपके मन में जो कुछ भी नहीं है, हो सकता है, लेकिन चूंकि आपने इसका उल्लेख नहीं किया है कि यह क्या है, मुझे लगता है कि एक जवाब यह होगा कि आप इसे दायरे और कार्यक्रम प्रवाह को नियंत्रित करके करेंगे।
उदाहरण के लिए, अगर आप इस तरह एक खेल नहीं लिखा होगा:
void play_level(level_number, level_data) {
Player player; //gets "re-initialized" at the beginning of each level using constructor
//code for level
}
void game() {
level_number = 1;
while (some_condition) {
play_level(level_number, level_data);
++level_number;
}
}
(बहुत किसी न किसी रूपरेखा विचार व्यक्त करने के लिए, करने के लिए नहीं:
initialize player
code for level 1
...
reinitialize player
code for level 2
...
etc
इसके बजाय आप के लिए प्रयास करता हूँ दूरस्थ रूप से संकलित हो।)
हाँ आप धोखा दे सकते हैं और प्लेसमेंट का उपयोग कर सकते हैं।
नोट: मैं इस सलाह नहीं:
#include <new>
reInitAnA(A& value)
{
value.~A(); // destroy the old one first.
new (&value) A(); // Call the constructor
// uses placement new to construct the new object
// in the old values location.
}
क्या नया विफल रहता है? – Jagannath
इस मामले में नया असफल नहीं हो सकता है (स्मृति आवंटन के मामले में) क्योंकि कोई स्मृति आवंटित नहीं की जाती है। कन्स्ट्रक्टर असफल हो सकता है और जैसे ही आप उम्मीद करेंगे अपवाद फेंक सकते हैं। –
संभवतः जगन्नाथ का अर्थ क्या है, क्या होगा यदि कोई अपवाद फेंक दिया गया हो, और पैरामीटर के रूप में पारित वस्तु उदा। कॉलर से संबंधित एक स्वचालित चर, या एक स्मार्ट सूचक द्वारा आयोजित गतिशील आवंटित वस्तु। विनाशक को दो बार कॉल करने के लिए कब वैध है, वैधता सुनिश्चित करने के लिए कोई कोड लिखने के बारे में कैसे जाता है? –
और जैसा कि ऊपर कुछ उत्तर ने सुझाव दिया reinitializing, यह नीचे की तरह एक काम करने के लिए बेहतर है। नीचे दिया गया कोड अपवाद सुरक्षित है।
T& reinitialize(int x, int y)
{
T other(x, y);
Swap(other); // this can't throw.
return *this;
}
सी ++ 11 में, आप यह कर सकते हैं:
#include <type_traits>
template <class T, typename... Args>
void Reconstruct(T& x, Args&&... args)
{
static_assert(!std::has_virtual_destructor<T>::value, "Unsafe");
x.~T();
new (&x) T(std::forward<Args>(args)...);
}
यह आपको किसी भी वस्तु को Reconstruct
गुजर मनमाना निर्माता पैरामीटर का उपयोग करने की अनुमति देता है। यह Clear
विधियों का एक समूह बनाए रखने से बच सकता है, और बग जो आसानी से अनजान हो सकते हैं अगर किसी बिंदु पर ऑब्जेक्ट बदलता है, और Clear
विधि अब कन्स्ट्रक्टर से मेल नहीं खाती है।
उपर्युक्त अधिकांश संदर्भों में ठीक काम करेगा, लेकिन अगर वर्चुअल विनाशक वाले व्युत्पन्न ऑब्जेक्ट के भीतर संदर्भ आधार के संदर्भ में है तो असफल हो जाएंगे। इस कारण से, उपर्युक्त कार्यान्वयन उन वस्तुओं के साथ उपयोग को रोकता है जिनमें वर्चुअल विनाशक होता है।
मैं आमतौर पर आधुनिक C++ निम्नलिखित लिखें:
SomeClass a;
...
a = decltype(a)();
यह नहीं सबसे प्रभावी तरीका है, के रूप में यह प्रभावी रूप से a
के एक ही प्रकार का एक और वस्तु निर्माण करती है और a
करने के लिए इसे प्रदान करती है हो सकता है, लेकिन यह काम करता है ज्यादातर मामलों में, आपको a
के प्रकार को याद रखने की आवश्यकता नहीं है, और यदि टाइप बदलता है तो यह अनुकूल होता है।
- 1. ऑब्जेक्ट ऑब्जेक्ट के बजाय हैंडलबार.जेएस पार्स ऑब्जेक्ट
- 2. जावास्क्रिप्ट [ऑब्जेक्ट ऑब्जेक्ट]
- 3. ऑब्जेक्ट पर फ़्लैट ऑब्जेक्ट?
- 4. (जावा) ऑब्जेक्ट इनपुटपुट ऑब्जेक्ट
- 5. ऑब्जेक्ट
- 6. ऑब्जेक्ट
- 7. ऑब्जेक्ट
- 8. ऑब्जेक्ट
- 9. ऑब्जेक्ट
- 10. ऑब्जेक्ट
- 11. ऑब्जेक्ट
- 12. ऑब्जेक्ट
- 13. ऑब्जेक्ट
- 14. ऑब्जेक्ट
- 15. ऑब्जेक्ट
- 16. ऑब्जेक्ट
- 17. ऑब्जेक्ट
- 18. ऑब्जेक्ट
- 19. ऑब्जेक्ट
- 20. ऑब्जेक्ट
- 21. ऑब्जेक्ट
- 22. gdb स्मृति ऑब्जेक्ट को ऑब्जेक्ट
- 23. किसी ऑब्जेक्ट को अस्थिर ऑब्जेक्ट
- 24. जावास्क्रिप्ट ऑब्जेक्ट और JSON ऑब्जेक्ट
- 25. ऑब्जेक्ट() और क्लास myClass (ऑब्जेक्ट)
- 26. _EPROCESS ऑब्जेक्ट और _KPROCESS ऑब्जेक्ट
- 27. Azure टूल्स - ऑब्जेक्ट रेफरेंस ऑब्जेक्ट
- 28. ऑब्जेक्ट को कॉल करने के बराबर हटाएं (ऑब्जेक्ट)। ऑब्जेक्ट()
- 29. असहज टाइपर: ऑब्जेक्ट [ऑब्जेक्ट ऑब्जेक्ट] पर कोई तरीका नहीं है '
- 30. क्या डाटा ऑब्जेक्ट ऑब्जेक्ट वैल्यू ऑब्जेक्ट के समान है?
पुनः आरंभ करने से आपका क्या मतलब है? – David
वेरिएबल्स को समान मान देते हैं जब उन्हें पहले बनाया गया था। – cpx
नील का समाधान "सर्वोत्तम" है, हालांकि आपके डिज़ाइन को फ़िक्सिंग की आवश्यकता है। – GManNickG