क्विक क्वेश्चन: डिजाइन के नजरिए से, ऐसा क्यों है, C ++ में, मदर-ऑफ-ऑल बेस-क्लास नहीं है, आमतौर object
पर अन्य भाषाओं में क्या है?
typedef
एस। अधिक सामान्य श्रेणी के पदानुक्रम के साथ, आप बस उपयोग कर सकते हैं object
या iterator
।
क्विक क्वेश्चन: डिजाइन के नजरिए से, ऐसा क्यों है, C ++ में, मदर-ऑफ-ऑल बेस-क्लास नहीं है, आमतौर object
पर अन्य भाषाओं में क्या है?
typedef
एस। अधिक सामान्य श्रेणी के पदानुक्रम के साथ, आप बस उपयोग कर सकते हैं object
या iterator
।
जवाबों:
स्ट्रॉन्स्ट्रुप के अक्सर पूछे जाने वाले प्रश्नों में निश्चित सत्तारूढ़ पाया जाता है । संक्षेप में, यह किसी भी अर्थ अर्थ को व्यक्त नहीं करता है। इसकी एक लागत होगी। कंटेनर के लिए टेम्प्लेट अधिक उपयोगी होते हैं।
C ++ में यूनिवर्सल क्लास ऑब्जेक्ट क्यों नहीं है?
हमें एक की आवश्यकता नहीं है: सामान्य प्रोग्रामिंग ज्यादातर मामलों में सांख्यिकीय रूप से सुरक्षित विकल्प प्रदान करता है। अन्य मामलों को कई विरासत का उपयोग करके नियंत्रित किया जाता है।
कोई उपयोगी सार्वभौमिक वर्ग नहीं है: वास्तव में सार्वभौमिक स्वयं का कोई शब्दार्थ नहीं है।
एक "सार्वभौमिक" वर्ग प्रकार और इंटरफेस के बारे में मैला सोच को प्रोत्साहित करता है और अतिरिक्त रन-टाइम जाँच की ओर जाता है।
एक सार्वभौमिक आधार वर्ग का उपयोग लागत का तात्पर्य करता है: वस्तुओं को बहुरूपी होना चाहिए; इसका मतलब है कि मेमोरी और एक्सेस कॉस्ट। हीप ऑब्जेक्ट्स स्वाभाविक रूप से कॉपी शब्दार्थ का समर्थन नहीं करते हैं। हीप ऑब्जेक्ट सरल scoped व्यवहार का समर्थन नहीं करते (जो संसाधन प्रबंधन को जटिल करता है)। एक सार्वभौमिक बेस क्लास डायनामिक_कास्ट और अन्य रन-टाइम चेकिंग के उपयोग को प्रोत्साहित करता है।
Objects must be heap-allocated to be polymorphic
- मुझे नहीं लगता कि यह कथन आम तौर पर सही है। आप निश्चित रूप से स्टैक पर एक पॉलीमॉर्फिक क्लास का एक उदाहरण बना सकते हैं और इसे पॉइंटरोफिक व्यवहार के आधार पर इसके बेस क्लास में से एक को पॉइंटर के रूप में पास कर सकते हैं।
Foo
एक संदर्भ-हैं- में Bar
जब Bar
यह नहीं है कि इनहेरिट Foo
, निर्धारणात्मक एक अपवाद फेंकता है। C ++ में, एक पॉइंटर-टू-फू को एक पॉइंटर-टू-बार में डालने का प्रयास सारा कॉनर को मारने के लिए एक रोबोट को समय पर वापस भेज सकता है।
आइए पहले यह सोचें कि आप पहले स्थान पर बेस-क्लास क्यों करना चाहते हैं। मैं कुछ अलग कारणों के बारे में सोच सकता हूं:
ये दो अच्छे कारण हैं कि स्मॉलटाक, रूबी और ऑब्जेक्टिव-सी ब्रांड की भाषाओं में बेस-क्लास हैं (तकनीकी रूप से, ऑब्जेक्टिव-सी में वास्तव में बेस-क्लास नहीं है, लेकिन सभी इरादों और उद्देश्यों के लिए, यह करता है)।
# 1 के लिए, C- ++ में टेम्प्लेट को शामिल करने से एक एकल इंटरफ़ेस के तहत सभी ऑब्जेक्ट्स को एकजुट करने वाली बेस-क्लास की आवश्यकता कम हो जाती है। उदाहरण के लिए:
void somethingGeneric(Base);
Derived object;
somethingGeneric(object);
अनावश्यक है, जब आप पैरामीट्रिक बहुरूपता के माध्यम से सभी तरह से अखंडता बनाए रख सकते हैं!
template <class T>
void somethingGeneric(T);
Derived object;
somethingGeneric(object);
# 2 के लिए, जबकि वस्तुनिष्ठ-सी में, स्मृति प्रबंधन प्रक्रियाएं एक वर्ग के कार्यान्वयन का हिस्सा हैं, और आधार वर्ग से विरासत में मिली हैं, C ++ में मेमोरी प्रबंधन विरासत के बजाय रचना का उपयोग करके किया जाता है। उदाहरण के लिए, आप एक स्मार्ट पॉइंटर रैपर को परिभाषित कर सकते हैं जो किसी भी प्रकार की वस्तुओं पर संदर्भ की गिनती करेगा:
template <class T>
struct refcounted
{
refcounted(T* object) : _object(object), _count(0) {}
T* operator->() { return _object; }
operator T*() { return _object; }
void retain() { ++_count; }
void release()
{
if (--_count == 0) { delete _object; }
}
private:
T* _object;
int _count;
};
फिर, ऑब्जेक्ट पर कॉल करने के तरीकों के बजाय, आप इसके आवरण में कॉलिंग के तरीकों को शामिल करेंगे। यह न केवल अधिक सामान्य प्रोग्रामिंग की अनुमति देता है: यह आपको अलग-अलग चिंताएं भी देता है (आदर्श रूप से, आपकी वस्तु को इस बारे में अधिक चिंतित होना चाहिए कि उसे क्या करना चाहिए, इसकी तुलना में उसकी स्मृति को विभिन्न स्थितियों में कैसे प्रबंधित किया जाना चाहिए)।
अंत में, ऐसी भाषा जिसमें C ++ जैसी प्राथमिक और वास्तविक दोनों वस्तुएं हैं, बेस-क्लास ( प्रत्येक मान के लिए एक सुसंगत इंटरफ़ेस ) होने के लाभ खो गए हैं, तब से आपके पास कुछ निश्चित मान हैं जो उस इंटरफ़ेस के अनुरूप नहीं हो सकते हैं। इस तरह की स्थिति में प्राइमिटिव्स का उपयोग करने के लिए, आपको उन्हें वस्तुओं में उठाने की जरूरत है (यदि आपका कंपाइलर स्वचालित रूप से ऐसा नहीं करेगा)। इससे बहुत जटिलता पैदा होती है।
तो, आपके प्रश्न का संक्षिप्त उत्तर: C ++ में बेस-क्लास नहीं है, क्योंकि टेम्प्लेट के माध्यम से पैरामीट्रिक पॉलीमॉर्फिज़्म होने पर इसकी आवश्यकता नहीं है।
object
( System.Object
) के लिए किया जा सकता है , लेकिन उन्हें होने की आवश्यकता नहीं है। संकलक के लिए, int
और System.Int32
उपनाम हैं और परस्पर विनिमय के लिए इस्तेमाल किया जा सकता है; जरूरत पड़ने पर रनटाइम बॉक्सिंग संभालती है।
std::shared_ptr
उपयोग किया जाना चाहिए।
C ++ वैरिएबल के लिए प्रमुख प्रतिमान पास-बाय-वैल्यू है, पास-बाय-रेफ नहीं। सब कुछ एक जड़ से प्राप्त करने के लिए मजबूर Object
करना उन्हें एक मूल्य ipse facto द्वारा पारित करना होगा।
(क्योंकि मान के रूप में किसी ऑब्जेक्ट को पैरामीटर के रूप में स्वीकार करना, परिभाषा के अनुसार इसे स्लाइस करके और उसकी आत्मा को हटा देगा)।
यह अवांछित है। C ++ आपको इस बारे में सोचता है कि क्या आप मूल्य या संदर्भ शब्दार्थ चाहते थे, जो आपको विकल्प दे रहा है। प्रदर्शन कंप्यूटिंग में यह एक बड़ी बात है।
Object
अपेक्षाकृत मामूली होगी।
समस्या यह है कि वहाँ सी ++ में इस तरह का है! यह है void
। :-) कोई भी पॉइंटर सुरक्षित रूप से निहित हो सकता है void *
, जिसमें पॉइंटर्स से लेकर बेसिक प्रकार, बिना वर्चुअल टेबल वाली कक्षाएं और वर्चुअल टेबल वाली कक्षाएं शामिल हैं।
चूँकि यह उन सभी श्रेणियों की वस्तुओं के अनुकूल होना चाहिए, void
जिसमें स्वयं आभासी विधियाँ नहीं हो सकती हैं। वर्चुअल फ़ंक्शंस और आरटीटीआई के बिना, टाइप पर कोई उपयोगी जानकारी प्राप्त नहीं की जा सकती void
(यह हर प्रकार से मेल खाती है, इसलिए केवल उन चीज़ों को बता सकता है जो एवरवाई टाइप के लिए सही हैं), लेकिन वर्चुअल फ़ंक्शंस और आरटीटीआई सरल प्रकारों को बहुत अप्रभावी बना देंगे और 10 ++ को होने से रोक देंगे। प्रत्यक्ष मेमोरी एक्सेस आदि के साथ निम्न स्तर की प्रोग्रामिंग के लिए उपयुक्त भाषा
तो, वहाँ इस प्रकार है। यह भाषा की निम्न-स्तरीय प्रकृति के कारण बहुत ही न्यूनतम (वास्तव में, खाली) इंटरफ़ेस प्रदान करता है। :-)
void
।
void
यह संकलित नहीं होगा और आपको यह त्रुटि मिलती है । जावा में आपके पास एक प्रकार का चर हो सकता है Object
और यह काम करेगा। यही अंतर void
और "वास्तविक" प्रकार है। शायद यह सच है कि void
सब कुछ के लिए आधार प्रकार है, लेकिन जैसा कि यह किसी भी निर्माता, तरीके या क्षेत्र प्रदान नहीं करता है, यह बताने का कोई तरीका नहीं है कि यह वहां है या नहीं। इस दावे को साबित या अस्वीकृत नहीं किया जा सकता है।
void
यह एक प्रकार है (और कुछ हद तक चतुर उपयोग की? :
खोज की गई है ), लेकिन यह अभी भी एक सार्वभौमिक आधार वर्ग होने से लंबा रास्ता है। एक बात के लिए, यह "एक अपूर्ण प्रकार है जिसे पूरा नहीं किया जा सकता है," और दूसरे के लिए, कोई void&
प्रकार नहीं है ।
C ++ एक जोरदार टाइप की गई भाषा है। फिर भी यह हैरान करने वाला है कि इसमें टेम्पलेट विशेषज्ञता के संदर्भ में एक सार्वभौमिक वस्तु प्रकार नहीं है।
उदाहरण के लिए, पैटर्न को लें
template <class T> class Hook;
template <class ReturnType, class ... ArgTypes>
class Hook<ReturnType (ArgTypes...)>
{
...
ReturnType operator () (ArgTypes... args) { ... }
};
जो के रूप में तुरंत किया जा सकता है
Hook<decltype(some_function)> ...;
अब मान लेते हैं कि हम किसी विशेष कार्य के लिए भी यही चाहते हैं। पसंद
template <auto fallback> class Hook;
template <auto fallback, class ReturnType, class ... ArgTypes>
class Hook<ReturnType fallback(ArgTypes...)>
{
...
ReturnType operator () (ArgTypes... args) { ... }
};
विशेष तात्कालिकता के साथ
Hook<some_function> ...
लेकिन अफसोस, भले ही वर्ग टी विशेषज्ञता के पहले किसी भी प्रकार (वर्ग या नहीं) के लिए खड़ा हो सकता है, कोई समकक्ष नहीं है auto fallback
(मैं इस संदर्भ में सबसे स्पष्ट सामान्य गैर-प्रकार के रूप में उस वाक्यविन्यास का उपयोग कर रहा हूं) जो किसी के लिए भी खड़ा हो सकता है विशेषज्ञता से पहले गैर-टाइप टेम्पलेट तर्क।
तो सामान्य तौर पर यह पैटर्न टाइप टेम्पलेट तर्क से गैर-टाइप टेम्पलेट तर्क में स्थानांतरित नहीं होता है।
सी ++ भाषा में बहुत सारे कोनों के साथ की तरह, इसका उत्तर "कोई समिति के सदस्य ने नहीं सोचा था"।
ReturnType fallback(ArgTypes...)
काम करेगा, तो यह खराब डिजाइन होगा। template <class T, auto fallback> class Hook; template <class ReturnType, class ... ArgTypes> class Hook<ReturnType (ArgTypes...), ReturnType(*fallback)(ArgTypes...)> ...
क्या आप चाहते हैं और इसका मतलब है कि Hook
लगातार प्रकार
C ++ को शुरू में "C with classes" कहा जाता था। यह C # की तरह कुछ और आधुनिक चीजों के विपरीत, C भाषा की प्रगति है। और आप सी ++ को भाषा के रूप में नहीं देख सकते हैं, लेकिन भाषाओं की नींव के रूप में (हां, मुझे स्कॉट मेयर्स की किताब इफेक्टिव सी ++ याद है)।
C अपने आप में भाषाओं का मिश्रण है, C प्रोग्रामिंग लैंग्वेज और इसका प्रीप्रोसेसर है।
C ++ एक और मिश्रण जोड़ता है:
वर्ग / वस्तुओं दृष्टिकोण
टेम्पलेट्स
एसटीएल
मुझे व्यक्तिगत रूप से कुछ चीजें पसंद नहीं हैं जो सीधे C से C ++ में आती हैं। एक उदाहरण एनम सुविधा है। जिस तरह से सी # डेवलपर को इसका उपयोग करने की अनुमति देता है वह बेहतर है: यह अपने स्वयं के दायरे में एनम को सीमित करता है, इसमें एक गणना गुण है और यह आसानी से चलने योग्य है।
जैसा कि C ++ C के साथ प्रतिगामी होना चाहता था, डिजाइनर C को C + में अपनी पूरी भाषा में प्रवेश करने की अनुमति देने के लिए बहुत ही अनुज्ञेय थे (कुछ सूक्ष्म अंतर हैं, लेकिन मुझे कोई भी चीज याद नहीं है कि आप C कम्पाइलर का उपयोग कर सकते हैं) C ++ कंपाइलर का उपयोग नहीं कर सका)।