एक गलत धारणा है: शुद्ध OOP की अवधारणा -outside विरासत, कि सी ++ नहीं है - "एक क्षय की क्षमता के साथ एक अनाम सदस्य के साथ रचना," एक से ज्यादा कुछ नहीं है।
आभासी कार्यों के अभाव (और नाशक विशेष नहीं है, इस अर्थ में) अपने वस्तु बहुरूपी नहीं करता है, लेकिन अगर तुम क्या कर रहे बस है "यह व्यवहार का पुन: उपयोग और देशी इंटरफ़ेस का पर्दाफाश" विरासत वास्तव में क्या करता है आप पूछा।
Destructors स्पष्ट रूप से एक दूसरे से कहा जाने के बाद से उनके कॉल हमेशा विनिर्देश द्वारा श्रृंखलित है की जरूरत नहीं है।
#include <iostream>
unsing namespace std;
class A
{
public:
A() { cout << "A::A()" << endl; }
~A() { cout << "A::~A()" << endl; }
void hello() { cout << "A::hello()" << endl; }
};
class B: public A
{
public:
B() { cout << "B::B()" << endl; }
~B() { cout << "B::~B()" << endl; }
void hello() { cout << "B::hello()" << endl; }
};
int main()
{
B b;
b.hello();
return 0;
}
इच्छा उत्पादन
A::A()
B::B()
B::hello()
B::~B()
A::~A()
बनाना एक
class B
{
public:
A a;
B() { cout << "B::B()" << endl; }
~B() { cout << "B::~B()" << endl; }
void hello() { cout << "B::hello()" << endl; }
};
के साथ बी में एम्बेड कि उत्पादन होगा बिल्कुल उसी।
एक सी ++ अनिवार्य परिणाम नहीं है, लेकिन सिर्फ एक सामान्य स्वीकार नहीं लिखा (इसके बारे में कल्पना में कुछ भी नहीं है: अलग एक यूबी एक आधार पर हटाने के कॉल) "अगर नाशक आभासी नहीं है निकाले जाते हैं मत करो" नियम जो सी ++ 99 से पहले उठता है, जब गतिशील विरासत और आभासी कार्यों द्वारा ओओपी एकमात्र प्रोग्रामिंग प्रतिमान सी ++ समर्थित था।
बेशक
दुनिया चारों ओर कई प्रोग्रामर स्कूल का उस तरह (एक ही है कि पुरातन के रूप में iostreams सिखाने के साथ उनकी हड्डियों बनाया, फिर सरणी और संकेत करने के लिए ले जाता है, और बहुत पिछले सबक पर शिक्षक कहते हैं, "ओह। .. तेहर भी एसटीएल है जिसमें वेक्टर, स्ट्रिंग और अन्य उन्नत फीचर्स हैं ") और आज भी, अगर सी ++ मल्टीपाडाडिग्म बन गया है, तब भी इस शुद्ध ओओपी नियम के साथ जोर देते हैं।
मेरे नमूने में ए :: ~ ए() वर्चुअल रूप से ए :: हैलो नहीं है। इसका क्या मतलब है?
सरल: इसी कारण A::hello
बुला B::hello
बुला का कारण नहीं बनेगा, A::~A()
फोन करने के लिए (हटाने) के द्वारा B::~B()
का कारण नहीं बनेगा। -इन आप शैली के पहले अभिकथन प्रोग्रामिंग आप स्वीकार कर सकते हैं, तो कोई कारण नहीं कि आप दूसरे स्वीकार नहीं कर सकते हैं। मेरी नमूने में कोई A* p = new B
कि delete p
एक के बाद प्राप्त होगा :: ~ एक आभासी नहीं है और मुझे पता है इसका क्या मतलब है।
वास्तव में है कि एक ही कारण है कि नहीं होगा, बी, A* p = &((new B)->a);
एक delete p;
साथ के लिए दूसरे उदाहरण का उपयोग करते हुए, हालांकि यह दूसरा मामला, पहले एक साथ पूरी तरह से दोहरे, कोई स्पष्ट कारणों के लिए दिलचस्प नहीं किसी को भी लग रहा है।
एकमात्र समस्या "रखरखाव" है, इस अर्थ में कि योपुर कोड एक ओओपी प्रोग्रामर द्वारा देखा जाता है- इसे अस्वीकार कर देगा, क्योंकि यह स्वयं में गलत नहीं है, लेकिन क्योंकि उसे ऐसा करने के लिए कहा गया है।
वास्तव में, "अगर नाशक आभासी नहीं है प्राप्त नहीं है" है, क्योंकि प्रोग्रामर के सबसे beleave भी कई प्रोग्रामर है कि पता नहीं है कि वे एक आधार के लिए एक सूचक पर हटाने के कॉल नहीं कर सकते देखते हैं कि। (माफ करना अगर यह विनम्र नहीं है, लेकिन प्रोग्रामिंग अनुभव के 30 साल के बाद मैं किसी अन्य कारण से नहीं देख सकते हैं!)
लेकिन आपके सवाल का अलग है: कॉलिंग बी
:: ~ बी() (हटाने या द्वारा स्कोप एंडिंग द्वारा) हमेशा ए :: ~ ए() के बाद ए (चाहे वह एम्बेडेड हो या विरासत में हो) परिणामस्वरूप किसी भी मामले में बी का हिस्सा होगा।
Luchian टिप्पणियों के बाद: अपरिभाषित व्यवहार ऊपर अपनी टिप्पणी में एक एक नहीं आभासी नाशक के साथ सूचक करने वाली एक-object's आधार पर एक हटाए जाने से संबंधित है alluded।
ओओपी स्कूल के अनुसार, यह परिणाम "नियम नहीं है यदि कोई आभासी विनाशक मौजूद नहीं है"।
मैं क्या कर रहा हूँ उनका कहना है, यहाँ, कि है कि स्कूल के कारणों के तथ्य यह है कि हर OOP उन्मुख वस्तु बहुरूपी हो गया है पर निर्भर करता है और सब कुछ बहुरूपी है वस्तु प्रतिस्थापन अनुमति देने के लिए एक आधार के लिए सूचक द्वारा पता होना चाहिए, है । उन दावे करके, वह स्कूल जानबूझकर व्युत्पन्न और गैर-प्रतिस्थापन के बीच छेड़छाड़ करने की कोशिश कर रहा है, ताकि एक शुद्ध ओओपी प्रोग्राम उस यूबी का अनुभव न करे।
मेरी स्थिति, बस, यह स्वीकार करती है कि सी ++ सिर्फ ओओपी नहीं है, और सभी सी ++ ऑब्जेक्ट्स डिफ़ॉल्ट रूप से ओओपी उन्मुख नहीं हैं, और, ओओपी स्वीकार करना हमेशा एक आवश्यक आवश्यकता नहीं है, यह भी स्वीकार करता है कि सी ++ विरासत हमेशा नहीं है जरूरी रूप से ओओपी प्रतिस्थापन के लिए सर्विसिंग।
std :: नक्शा polymorphic नहीं है इसलिए यह बदलने योग्य नहीं है। माईमैप वही है: पॉलिमॉर्फिक नहीं और प्रतिस्थापन योग्य नहीं।
इसे बस std :: map का पुन: उपयोग करना होगा और उसी std :: मानचित्र इंटरफ़ेस का पर्दाफाश करना होगा। और विरासत सिर्फ पुनर्लेखित कार्यों के लंबे बॉयलरप्लेट से बचने का तरीका है जो केवल पुन: उपयोग किए गए लोगों को कॉल करता है।
MyMap में वर्चुअल dtor नहीं होगा क्योंकि std :: मानचित्र में कोई नहीं है। और यह मेरे लिए- एक सी ++ प्रोग्रामर को बताने के लिए पर्याप्त है कि ये बहुलक वस्तुएं नहीं हैं और इसका उपयोग दूसरे के स्थान पर नहीं किया जाना चाहिए।
मुझे यह मानना है कि आज इस स्थिति को अधिकांश सी ++ विशेषज्ञों द्वारा साझा नहीं किया गया है। लेकिन मुझे लगता है (मेरी एकमात्र व्यक्तिगत राय) यह केवल उनके इतिहास की वजह से है, जो ओओपी से सेवा करने के लिए एक सिद्धांत के रूप में संबंधित है, सी ++ की आवश्यकता के कारण नहीं। मेरे लिए सी ++ एक शुद्ध ओओपी भाषा नहीं है और अनिवार्य रूप से हमेशा ओओपी प्रतिमान का पालन नहीं करना चाहिए, एक संदर्भ में जहां ओओपी का पालन नहीं किया जाता है या आवश्यक है।
+1 हमेशा विरासत की बजाय संरचना का पक्ष लें। अभी भी इच्छा है कि लपेटने के लिए आवश्यक सभी बॉयलरप्लेट कोड को कम करने का कोई तरीका था। – daramarak
@ दशमराक: तो क्या मैं, अगर कुछ विशेषता 'asribute.insert' का उपयोग कर सकता हूं, तो काम कर सकता है! दूसरी तरफ, यह बहुत दुर्लभ है कि आपको वास्तव में सभी विधियों की आवश्यकता है, और रैपिंग अर्थपूर्ण नाम देने और उच्च स्तरीय प्रकार लेने का मौका देता है :) –
@ दशमराक: * फिर भी इच्छा है कि सभी बॉयलरप्लेट कोड को कम करने का कोई तरीका था लपेटने के लिए आवश्यक *: हाँ, वहाँ है: विरासत। लेकिन प्रोग्रामर स्वयं को आश्वस्त हैं कि उन्हें इसका उपयोग नहीं करना चाहिए ... क्योंकि वे हमेशा इसे "एक" के रूप में समझते हैं। लेकिन यह एक आवश्यकता नहीं है, सिर्फ एक सार्वजनिक विश्वास है। –