2010-01-19 7 views
6

मुझे पता है कि सी ++ में इसकी अनुमति नहीं है, लेकिन क्यों? अगर इसे अनुमति दी गई तो क्या समस्याएं होंगी?हम सी ++ में एक अमूर्त वर्ग के लिए वस्तुएं क्यों नहीं बना सकते?

+1

जाहिर है संचार में कहीं अंतर है। क्या आप एक कोड उदाहरण और अपने उच्च स्तरीय लक्ष्य दे सकते हैं? – GManNickG

+0

@GMan I dint कुछ कोड लिखते समय इस पर आते हैं। मैं सिर्फ ठोस कारण जानना चाहता हूं कि हम एक अमूर्त वर्ग के लिए वस्तु क्यों नहीं बना सकते? क्या स्मृति आवंटन से संबंधित समस्या है, या क्या यह किसी और चीज़ से चिंतित है? और वास्तव में समस्या क्या है? यहाँ मेरा पूरा बिंदु है। – Moeb

+0

क्योंकि यह अनुमति देने के लिए तार्किक नहीं है। यह जानवर (एक उदाहरण) बनाने के लिए XXX पूछना (यहां अपना देवता चुनें) जैसा है। यह संभव नहीं है कि उसे एक विशिष्ट प्रकार का पशु बनाना होगा (जैसे 'बतख': कक्षा बतख का एक उदाहरण)। पशु की अवधारणा सार है वहां कोई वस्तु नहीं है जो केवल पशु हैं। –

उत्तर

22

आपके 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) करने के समान है, bthis पॉइंटर के रूप में गुजर रहा है।

तो, जब वर्चुअल विधियां मौजूद होती हैं, तो आकार की कक्षा एक सूचक (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 भी मौजूद नहीं है। उपरोक्त कोड अपरिभाषित व्यवहार है, और बीच में कुछ भी के साथ, कुछ भी क्रैश करने के लिए कुछ भी नहीं कर सकता है। (या बदतर।)

इस बारे में सोचें कि शुद्ध सार कार्य क्या दर्शाता है। याद रखें, फ़ंक्शन कोई डेटा नहीं लेते हैं, वे केवल डेटा का उपयोग करने का वर्णन करते हैं। एक शुद्ध अमूर्त कार्य कहता है: "मैं इस विधि को कॉल करना चाहता हूं और मेरा डेटा छेड़छाड़ करना चाहता हूं। आप यह कैसे करते हैं।"

तो जब आप कहते हैं, "ठीक है, चलो एक अमूर्त विधि कहें", आप उपर्युक्त के साथ जवाब दे रहे हैं: "मेरे ऊपर? नहीं, आप इसे करते हैं।" जिसके लिए यह जवाब देगा "@ #^@ # ^"। यह किसी को यह बताना समझ में नहीं आता है कि "यह करें", "नहीं" कह रहा है।

सीधे अपने सवाल का जवाब करने के लिए:

"हम क्यों नहीं एक वस्तु एक अमूर्त वर्ग के लिए बना सकते हैं?"

उम्मीद है कि अब आप देख, सार कक्षाएं केवल कार्यक्षमता ठोस वर्ग ऐसा करने में सक्षम होना चाहिए परिभाषित सार वर्ग में ही केवल एक नीली प्रिंट है,। आप नीले-प्रिंट में नहीं रहते, आप रहते हैं नीले रंग के प्रिंटों को लागू करने वाले घरों में

+0

@Gman: सभी विवरणों के लिए धन्यवाद – Moeb

3

एक कक्षा को केवल सार घोषित किया जा सकता है जहां इसकी कोई सार विधि नहीं है। मुझे लगता है कि सिद्धांत में तत्काल हो सकता है लेकिन कक्षा डिजाइनर आपको नहीं चाहता है। इसमें अनपेक्षित परिणाम हो सकते हैं।

आमतौर पर सार वर्गों में अमूर्त विधियां होती हैं। उन्हें सरल कारणों से तत्काल नहीं किया जा सकता है कि वे उन तरीकों को याद कर रहे हैं।

+0

हां, क्या "अनपेक्षित परिणाम" संभव हैं? मान लीजिए कि मैं गारंटी देता हूं कि मेरा ऑब्जेक्ट कभी भी इसके किसी भी काम को कॉल नहीं करेगा? – Moeb

+1

एक विधि घोषित करके एक वर्ग ने अनुबंध किया है कि आप उस विधि को कॉल कर सकते हैं। कक्षा अनुबंध वर्णन करेगा कि वह कार्य क्या करता है, यह कौन सा तर्क लेता है और यह क्या लौटाता है (यदि कुछ भी हो)। एक अमूर्त वर्ग उस अनुबंध को पूरा करने में सक्षम नहीं होगा। – cletus

+0

यदि आप एक विधि 'अमूर्त' बनाते हैं तो आप उम्मीद करते हैं कि इसे * इसके उप-वर्ग द्वारा कार्यान्वित किया जाना चाहिए, और चाहते हैं कि संकलक आपके लिए त्रुटियों को पकड़ ले, जब उस विधि को सबक्लास के माध्यम से नहीं कहा जाता है। यदि आपको उस विधि को कॉल करने की आवश्यकता नहीं है, तो बस इसे छोड़ दें या डिफ़ॉल्ट कार्यान्वयन की आपूर्ति करें। – kennytm

3

क्योंकि तर्कसंगत रूप से यह कोई समझ नहीं आता है।

एक सार श्रेणी एक अधूरा है जो अपूर्ण है।
यह इंगित करता है कि इसे पूरा करने के लिए किन चीजों को भरने की आवश्यकता है लेकिन उन बिट्स के बिना यह पूरा नहीं हुआ है।

मेरा पहला उदाहरण शतरंज का खेल था:
इस खेल में विभिन्न प्रकार के कई टुकड़े हैं (राजा, रानी, ​​Pawn ... आदि)।

लेकिन प्रकार के टुकड़े की वास्तविक वस्तुएं नहीं हैं, लेकिन सभी वस्तुएं टुकड़े से प्राप्त वस्तुओं के उदाहरण हैं। आपके पास ऐसी चीज़ का ऑब्जेक्ट कैसे हो सकता है जो पूरी तरह परिभाषित नहीं है। टुकड़े की वस्तु बनाने में कोई बात नहीं है क्योंकि खेल नहीं जानता कि यह कैसे चलता है (यह अमूर्त हिस्सा है)। यह जानता है कि यह स्थानांतरित हो सकता है लेकिन यह नहीं करता कि यह कैसे करता है।

5

समस्या है तो बस इस:

  • कार्यक्रम क्या करना चाहिए एक सार विधि कहा जाता है जब?
  • और इससे भी बदतर: गैर-शून्य फ़ंक्शन के लिए क्या लौटाया जाना चाहिए?

एप्लिकेशन को संभावित रूप से क्रैश या रनटाइम अपवाद को फेंकना होगा और इस प्रकार इससे परेशानी होगी। आप हर अमूर्त कार्य को डमी-कार्यान्वित नहीं कर सकते हैं।

0

सार कक्षाएं तत्काल बेकार होंगी, क्योंकि आप "शुद्ध वर्चुअल फ़ंक्शन" नामक बहुत अधिक देख रहे होंगे। :)

ऐसा लगता है: हम सभी जानते हैं कि एक कार में 3 पेडल और स्टीयरिंग व्हील और एक गियर स्टिक होगा। अब, अगर यह होगा, और वहां 3 पेडल और गियर स्टिक और एक पहिया का उदाहरण होगा, मैं इसे खरीद नहीं रहा हूं, मुझे सीट, दरवाजे, एसी आदि जैसे कार चाहिए, वास्तव में पेडल के साथ अस्तित्व में होने के अलावा कुछ और यही है कि अमूर्त वर्ग मुझसे वादा नहीं करता है, लागू करता है।

2

सार कक्षाएं परिभाषा द्वारा परिभाषित नहीं हैं। उन्हें आवश्यकता है कि व्युत्पन्न, ठोस कक्षाएं हों। एक सार वर्ग क्या होगा यदि उसके पास शुद्ध आभासी नहीं है (अनुपूरक) कार्य?

0

यह प्रश्न का एक ही वर्ग है क्योंकि मैं एक कॉन्स्ट चर के मूल्य को क्यों नहीं बदल सकता , मैं अन्य वर्गों से निजी वर्ग के सदस्यों तक क्यों नहीं पहुंच सकता या मैं अंतिम तरीकों को ओवरराइड क्यों नहीं कर सकता।

क्योंकि ऐसा करने से आपको रोकने के लिए इन कीवर्ड का उद्देश्य है। क्योंकि कोड के लेखक को कुछ असामान्य कारणों से इतना खतरनाक, अवांछित या असंभव समझा जाता है, जैसे विशिष्ट कार्यों की कमी, जिन्हें विशिष्ट बाल वर्गों द्वारा जोड़ा जाना आवश्यक है। यह वास्तव में नहीं है कि आप तत्काल नहीं कर सकते क्योंकि कक्षा एक आभासी है। यह है कि एक वर्ग को तत्काल करने में असमर्थता इसे वर्चुअल के रूप में परिभाषित करती है (और यदि एक वर्ग जिसे तत्काल नहीं किया जा सकता है वह वर्चुअल नहीं है, तो यह एक त्रुटि है। दूसरी तरफ जाता है, अगर दिया गया वर्ग का उदाहरण समझ में आता है, तो यह नहीं होना चाहिए वर्चुअल के रूप में चिह्नित)

1

हम एक अमूर्त वर्ग का ऑब्जेक्ट क्यों नहीं बना सकते?

बस सार वर्ग में अमूर्त विधियां हैं (जिसका अर्थ है शरीर के बिना कार्य) और हम अमूर्त तरीकों को कार्यक्षमता नहीं दे सकते हैं। और यदि हम अमूर्त तरीकों को कार्यक्षमता देने का प्रयास करते हैं तो अमूर्त वर्ग और वर्चुअल क्लास के बीच कोई अंतर नहीं होगा। तो आखिरकार यदि हम एक अबास्ट्रा क्लास का ऑब्जेक्ट बनाते हैं तो बेकार कार्यों या अमूर्त तरीकों को कॉल करने के लिए कोई मजा नहीं है क्योंकि वे कार्यक्षमता के बिना हैं .. इसलिए ऐसा कोई भी भाषा हमें अमूर्त वर्ग का ऑब्जेक्ट बनाने की अनुमति नहीं देती है ..

+0

आपका उत्तर उत्तर में दिए गए उत्तर में कुछ भी नहीं जोड़ता है ... 2010। – alestanis

0

मूल रूप से ऑब्जेक्ट का निर्माण सदस्य चर और सदस्य कार्यों के लिए स्मृति आवंटन के लिए ज़िम्मेदार है। लेकिन यहां, शुद्ध वर्चुअल फ़ंक्शन में हमारे पास व्युत्पन्न कक्षा में घोषणा और परिभाषा है। इसलिए ऑब्जेक्ट का निर्माण त्रुटि उत्पन्न करता है।

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