मुझे पता है कि सी ++ में इसकी अनुमति नहीं है, लेकिन क्यों? अगर इसे अनुमति दी गई तो क्या समस्याएं होंगी?हम सी ++ में एक अमूर्त वर्ग के लिए वस्तुएं क्यों नहीं बना सकते?
उत्तर
आपके other question द्वारा निर्णय लेते हुए, ऐसा लगता है कि आप समझ नहीं पाते कि कक्षाएं कैसे संचालित होती हैं। कक्षाएं उन कार्यों का संग्रह हैं जो डेटा पर काम करती हैं।
कार्यों में कक्षा में कोई स्मृति नहीं है। निम्नलिखित वर्ग:
struct dumb_class
{
void foo(){}
void bar(){}
void baz(){}
// .. for all eternity
int i;
};
int
का एक आकार है। कोई फर्क नहीं पड़ता कि आपके पास कितने काम हैं, यह कक्षा केवल int
पर संचालित होने वाली जगह ले लेगी। जब आप इस कक्षा में कोई फ़ंक्शन कॉल करते हैं, तो कंपाइलर आपको उस स्थान पर एक पॉइंटर पास करेगा जहां कक्षा में डेटा संग्रहीत किया जाता है; यह this
सूचक है।
तो, फ़ंक्शन कहीं मेमोरी में स्थित है, आपके प्रोग्राम की शुरुआत में एक बार लोड हो गया है, और ऑपरेट करने के लिए डेटा के साथ कॉल करने का इंतजार है।
वर्चुअल फ़ंक्शन अलग हैं। सी ++ मानक अनिवार्य है कि वर्चुअल फ़ंक्शंस का व्यवहार कैसे होना चाहिए, केवल यही व्यवहार होना चाहिए। आम तौर पर, कार्यान्वयन का उपयोग वर्चुअल टेबल या कम के लिए vtable कहा जाता है। एक vtable फ़ंक्शन पॉइंटर्स की एक तालिका है, जो सामान्य कार्यों की तरह है, केवल एक बार आवंटित हो जाती है।
इस वर्ग ले लो, और हमारे implementor vtables का उपयोग करता है मान:
struct base { virtual void foo(void); };
struct derived { virtual void foo(void); };
संकलक दो vtables, आधार के लिए एक और व्युत्पन्न के लिए एक बनाने के लिए की आवश्यकता होगी। वे इस तरह कुछ देखेंगे:
typedef /* some generic function pointer type */ func_ptr;
func_ptr __baseTable[] = {&base::foo};
func_ptr __derivedTable[] = {&derived::foo};
यह इस तालिका का उपयोग कैसे करता है? जब आप उपरोक्त वर्ग का उदाहरण बनाते हैं, तो संकलक एक छिपे हुए सूचक में फिसल जाता है, जो सही vtable को इंगित करेगा। तो जब आप कहते हैं:
derived d;
base* b = &d;
b->foo();
अंतिम पंक्ति को क्रियान्वित करने पर, यह सही तालिका (इस मामले में __derivedTable
) को जाता है सही सूचकांक (0 इस मामले में) को जाता है, और कहा कि समारोह कहता है। जैसा कि आप देख सकते हैं, यह derived::foo
पर कॉल करना समाप्त कर देगा, जो वास्तव में होना चाहिए।
नोट, बाद में, यह derived::foo(b)
करने के समान है, b
this
पॉइंटर के रूप में गुजर रहा है।
तो, जब वर्चुअल विधियां मौजूद होती हैं, तो आकार की कक्षा एक सूचक (Vtable के सूचक) द्वारा बढ़ेगी। एकाधिक विरासत इसे थोड़ा सा बदलती है, लेकिन यह ज्यादातर समान है। आप C++-FAQ पर अधिक जानकारी प्राप्त कर सकते हैं।
अब, आपके प्रश्न के लिए। मेरे पास है:
struct base { virtual void foo(void) = 0; }; // notice the = 0
struct derived { virtual void foo(void); };
और base::foo
में कोई कार्यान्वयन नहीं है। यह base::foo
एक शुद्ध सारणी समारोह बनाता है। इसलिए, अगर मैं इसे कॉल करना चाहता था, जैसे ऊपर:
derived d;
base* b = &d;
base::foo(b);
हमें किस व्यवहार की अपेक्षा करनी चाहिए? शुद्ध आभासी विधि होने के नाते, base::foo
भी मौजूद नहीं है। उपरोक्त कोड अपरिभाषित व्यवहार है, और बीच में कुछ भी के साथ, कुछ भी क्रैश करने के लिए कुछ भी नहीं कर सकता है। (या बदतर।)
इस बारे में सोचें कि शुद्ध सार कार्य क्या दर्शाता है। याद रखें, फ़ंक्शन कोई डेटा नहीं लेते हैं, वे केवल डेटा का उपयोग करने का वर्णन करते हैं। एक शुद्ध अमूर्त कार्य कहता है: "मैं इस विधि को कॉल करना चाहता हूं और मेरा डेटा छेड़छाड़ करना चाहता हूं। आप यह कैसे करते हैं।"
तो जब आप कहते हैं, "ठीक है, चलो एक अमूर्त विधि कहें", आप उपर्युक्त के साथ जवाब दे रहे हैं: "मेरे ऊपर? नहीं, आप इसे करते हैं।" जिसके लिए यह जवाब देगा "@ #^@ # ^"। यह किसी को यह बताना समझ में नहीं आता है कि "यह करें", "नहीं" कह रहा है।
सीधे अपने सवाल का जवाब करने के लिए:
"हम क्यों नहीं एक वस्तु एक अमूर्त वर्ग के लिए बना सकते हैं?"
उम्मीद है कि अब आप देख, सार कक्षाएं केवल कार्यक्षमता ठोस वर्ग ऐसा करने में सक्षम होना चाहिए परिभाषित सार वर्ग में ही केवल एक नीली प्रिंट है,। आप नीले-प्रिंट में नहीं रहते, आप रहते हैं नीले रंग के प्रिंटों को लागू करने वाले घरों में
@Gman: सभी विवरणों के लिए धन्यवाद – Moeb
एक कक्षा को केवल सार घोषित किया जा सकता है जहां इसकी कोई सार विधि नहीं है। मुझे लगता है कि सिद्धांत में तत्काल हो सकता है लेकिन कक्षा डिजाइनर आपको नहीं चाहता है। इसमें अनपेक्षित परिणाम हो सकते हैं।
आमतौर पर सार वर्गों में अमूर्त विधियां होती हैं। उन्हें सरल कारणों से तत्काल नहीं किया जा सकता है कि वे उन तरीकों को याद कर रहे हैं।
हां, क्या "अनपेक्षित परिणाम" संभव हैं? मान लीजिए कि मैं गारंटी देता हूं कि मेरा ऑब्जेक्ट कभी भी इसके किसी भी काम को कॉल नहीं करेगा? – Moeb
एक विधि घोषित करके एक वर्ग ने अनुबंध किया है कि आप उस विधि को कॉल कर सकते हैं। कक्षा अनुबंध वर्णन करेगा कि वह कार्य क्या करता है, यह कौन सा तर्क लेता है और यह क्या लौटाता है (यदि कुछ भी हो)। एक अमूर्त वर्ग उस अनुबंध को पूरा करने में सक्षम नहीं होगा। – cletus
यदि आप एक विधि 'अमूर्त' बनाते हैं तो आप उम्मीद करते हैं कि इसे * इसके उप-वर्ग द्वारा कार्यान्वित किया जाना चाहिए, और चाहते हैं कि संकलक आपके लिए त्रुटियों को पकड़ ले, जब उस विधि को सबक्लास के माध्यम से नहीं कहा जाता है। यदि आपको उस विधि को कॉल करने की आवश्यकता नहीं है, तो बस इसे छोड़ दें या डिफ़ॉल्ट कार्यान्वयन की आपूर्ति करें। – kennytm
क्योंकि तर्कसंगत रूप से यह कोई समझ नहीं आता है।
एक सार श्रेणी एक अधूरा है जो अपूर्ण है।
यह इंगित करता है कि इसे पूरा करने के लिए किन चीजों को भरने की आवश्यकता है लेकिन उन बिट्स के बिना यह पूरा नहीं हुआ है।
मेरा पहला उदाहरण शतरंज का खेल था:
इस खेल में विभिन्न प्रकार के कई टुकड़े हैं (राजा, रानी, Pawn ... आदि)।
लेकिन प्रकार के टुकड़े की वास्तविक वस्तुएं नहीं हैं, लेकिन सभी वस्तुएं टुकड़े से प्राप्त वस्तुओं के उदाहरण हैं। आपके पास ऐसी चीज़ का ऑब्जेक्ट कैसे हो सकता है जो पूरी तरह परिभाषित नहीं है। टुकड़े की वस्तु बनाने में कोई बात नहीं है क्योंकि खेल नहीं जानता कि यह कैसे चलता है (यह अमूर्त हिस्सा है)। यह जानता है कि यह स्थानांतरित हो सकता है लेकिन यह नहीं करता कि यह कैसे करता है।
समस्या है तो बस इस:
- कार्यक्रम क्या करना चाहिए एक सार विधि कहा जाता है जब?
- और इससे भी बदतर: गैर-शून्य फ़ंक्शन के लिए क्या लौटाया जाना चाहिए?
एप्लिकेशन को संभावित रूप से क्रैश या रनटाइम अपवाद को फेंकना होगा और इस प्रकार इससे परेशानी होगी। आप हर अमूर्त कार्य को डमी-कार्यान्वित नहीं कर सकते हैं।
सार कक्षाएं तत्काल बेकार होंगी, क्योंकि आप "शुद्ध वर्चुअल फ़ंक्शन" नामक बहुत अधिक देख रहे होंगे। :)
ऐसा लगता है: हम सभी जानते हैं कि एक कार में 3 पेडल और स्टीयरिंग व्हील और एक गियर स्टिक होगा। अब, अगर यह होगा, और वहां 3 पेडल और गियर स्टिक और एक पहिया का उदाहरण होगा, मैं इसे खरीद नहीं रहा हूं, मुझे सीट, दरवाजे, एसी आदि जैसे कार चाहिए, वास्तव में पेडल के साथ अस्तित्व में होने के अलावा कुछ और यही है कि अमूर्त वर्ग मुझसे वादा नहीं करता है, लागू करता है।
सार कक्षाएं परिभाषा द्वारा परिभाषित नहीं हैं। उन्हें आवश्यकता है कि व्युत्पन्न, ठोस कक्षाएं हों। एक सार वर्ग क्या होगा यदि उसके पास शुद्ध आभासी नहीं है (अनुपूरक) कार्य?
यह प्रश्न का एक ही वर्ग है क्योंकि मैं एक कॉन्स्ट चर के मूल्य को क्यों नहीं बदल सकता , मैं अन्य वर्गों से निजी वर्ग के सदस्यों तक क्यों नहीं पहुंच सकता या मैं अंतिम तरीकों को ओवरराइड क्यों नहीं कर सकता।
क्योंकि ऐसा करने से आपको रोकने के लिए इन कीवर्ड का उद्देश्य है। क्योंकि कोड के लेखक को कुछ असामान्य कारणों से इतना खतरनाक, अवांछित या असंभव समझा जाता है, जैसे विशिष्ट कार्यों की कमी, जिन्हें विशिष्ट बाल वर्गों द्वारा जोड़ा जाना आवश्यक है। यह वास्तव में नहीं है कि आप तत्काल नहीं कर सकते क्योंकि कक्षा एक आभासी है। यह है कि एक वर्ग को तत्काल करने में असमर्थता इसे वर्चुअल के रूप में परिभाषित करती है (और यदि एक वर्ग जिसे तत्काल नहीं किया जा सकता है वह वर्चुअल नहीं है, तो यह एक त्रुटि है। दूसरी तरफ जाता है, अगर दिया गया वर्ग का उदाहरण समझ में आता है, तो यह नहीं होना चाहिए वर्चुअल के रूप में चिह्नित)
हम एक अमूर्त वर्ग का ऑब्जेक्ट क्यों नहीं बना सकते?
बस सार वर्ग में अमूर्त विधियां हैं (जिसका अर्थ है शरीर के बिना कार्य) और हम अमूर्त तरीकों को कार्यक्षमता नहीं दे सकते हैं। और यदि हम अमूर्त तरीकों को कार्यक्षमता देने का प्रयास करते हैं तो अमूर्त वर्ग और वर्चुअल क्लास के बीच कोई अंतर नहीं होगा। तो आखिरकार यदि हम एक अबास्ट्रा क्लास का ऑब्जेक्ट बनाते हैं तो बेकार कार्यों या अमूर्त तरीकों को कॉल करने के लिए कोई मजा नहीं है क्योंकि वे कार्यक्षमता के बिना हैं .. इसलिए ऐसा कोई भी भाषा हमें अमूर्त वर्ग का ऑब्जेक्ट बनाने की अनुमति नहीं देती है ..
आपका उत्तर उत्तर में दिए गए उत्तर में कुछ भी नहीं जोड़ता है ... 2010। – alestanis
मूल रूप से ऑब्जेक्ट का निर्माण सदस्य चर और सदस्य कार्यों के लिए स्मृति आवंटन के लिए ज़िम्मेदार है। लेकिन यहां, शुद्ध वर्चुअल फ़ंक्शन में हमारे पास व्युत्पन्न कक्षा में घोषणा और परिभाषा है। इसलिए ऑब्जेक्ट का निर्माण त्रुटि उत्पन्न करता है।
- 1. जावा में एक अमूर्त वर्ग में एक निजी एक्सेस संशोधक क्यों है, भले ही हम एक अमूर्त वर्ग का उदाहरण नहीं बना सकते?
- 2. क्यों हम इंटरफ़ेस/अमूर्त वर्ग में साझा (स्थैतिक) फ़ंक्शन/विधियां नहीं कर सकते हैं?
- 3. क्या हम जावा में सार्वजनिक स्थैतिक अमूर्त वर्ग बना सकते हैं?
- 4. हम राज्य में किस प्रकार की वस्तुएं रख सकते हैं?
- 5. सी # बेस/अमूर्त वर्ग
- 6. सी # हम स्थिर संपत्ति को ओवरराइड क्यों नहीं कर सकते?
- 7. सार कक्षाएं, हम निजी मूल्य और var वर्ग के सदस्य की घोषणा क्यों नहीं कर सकते?
- 8. हम एक ही कक्षा के अंदर एक वर्ग की वस्तु क्यों नहीं घोषित कर सकते हैं?
- 9. वहाँ एक अमूर्त वर्ग
- 10. अमूर्त वर्ग
- 11. सी # प्रतिनिधि और अमूर्त वर्ग
- 12. एक अमूर्त वर्ग
- 13. अमूर्त वर्ग और इंटरफ़ेस
- 14. अमूर्त वर्ग
- 15. सी # इंटरफेस खाली अमूर्त वर्ग
- 16. मैं एक अमूर्त वर्ग है एक अमूर्त वर्ग
- 17. आप PHP में अमूर्त कक्षाओं से अमूर्त कार्यों को क्यों नहीं बुला सकते?
- 18. एक सामान्य अमूर्त वर्ग
- 19. क्या हम एक इंटरफ़ेस का ऑब्जेक्ट बना सकते हैं?
- 20. एक अमूर्त वर्ग एक और अमूर्त वर्ग मुद्दा
- 21. मुझे सी ++ में एक अमूर्त वर्ग के लिए वर्चुअल विनाशक घोषित क्यों करना चाहिए?
- 22. अमूर्त वर्ग
- 23. सी # त्रुटि संदेश "अमूर्त वर्ग या इंटरफ़ेस का एक उदाहरण नहीं बना सकता"
- 24. एक अमूर्त वर्ग
- 25. एक अमूर्त वर्ग
- 26. हम जावा में पॉइंटर्स का उपयोग क्यों नहीं कर सकते?
- 27. अमूर्त बनाम अमूर्त वर्ग
- 28. एक अमूर्त वर्ग
- 29. अमूर्त वर्ग
- 30. एक अमूर्त वर्ग क्या है?
जाहिर है संचार में कहीं अंतर है। क्या आप एक कोड उदाहरण और अपने उच्च स्तरीय लक्ष्य दे सकते हैं? – GManNickG
@GMan I dint कुछ कोड लिखते समय इस पर आते हैं। मैं सिर्फ ठोस कारण जानना चाहता हूं कि हम एक अमूर्त वर्ग के लिए वस्तु क्यों नहीं बना सकते? क्या स्मृति आवंटन से संबंधित समस्या है, या क्या यह किसी और चीज़ से चिंतित है? और वास्तव में समस्या क्या है? यहाँ मेरा पूरा बिंदु है। – Moeb
क्योंकि यह अनुमति देने के लिए तार्किक नहीं है। यह जानवर (एक उदाहरण) बनाने के लिए XXX पूछना (यहां अपना देवता चुनें) जैसा है। यह संभव नहीं है कि उसे एक विशिष्ट प्रकार का पशु बनाना होगा (जैसे 'बतख': कक्षा बतख का एक उदाहरण)। पशु की अवधारणा सार है वहां कोई वस्तु नहीं है जो केवल पशु हैं। –