दिलचस्प पोस्ट
टेक्स्टफ़ाइल कहां रखा जाए मैं एक्लिप्स में उपयोग करना चाहता हूं? पंक्ति-स्तरीय ट्रिगर बनाम स्टेटमेंट-स्तरीय ट्रिगर अजगर में opencv का उपयोग करके छवि क्षेत्र की प्रतिलिपि कैसे करें? AirPrint के लिए उद्देश्य-सी कोड विम में regex मैच छोड़कर सब कुछ निकालें आधा गेज / स्पीडोमीटर को आकर्षित करना (जावास्क्रिप्ट कैनवास या जावा स्विंग उदाहरण की आवश्यकता) पायथन टाइम। नींद HTML तालिका सेल स्वरूपित करें ताकि पाठ के रूप में Excel स्वरूप? Python अनुरोध पुस्तकालय के साथ एक पोस्ट अनुरोध में कुकीज़ कैसे भेजें? हैश टेबल्स पर द्विआधारी खोज के पेड़ के फायदे एंड्रॉइड क्लासनोटफ़ाउंड अपवाद बाइनरी कॉलेशन का क्या प्रभाव पड़ता है? स्थानीय अधिसूचना को दोबारा अंतराल कस्टम समय अंतराल कैसे सेट करें? जेएनआई के माध्यम से एक एपलेट से एक DLL कॉल करना एक आकार में छवि / ग्राफिक

सी ++ में बनाया गया एक वीटेल कब है?

जब वास्तव में कंपाइलर एक वर्चुअल फ़ंक्शन तालिका बनाते हैं?

1) जब कक्षा में कम से कम एक आभासी फ़ंक्शन होता है।

या

2) जब तत्काल बेस क्लास में कम से कम एक वर्चुअल फ़ंक्शन होता है।

या

3) जब पदानुक्रम के किसी भी स्तर पर कोई अभिभावक वर्ग कम से कम एक आभासी फ़ंक्शन होता है।

इस से संबंधित प्रश्न: क्या सी ++ पदानुक्रम में गतिशील प्रेषण छोड़ना संभव है?

उदाहरण के लिए निम्नलिखित उदाहरण पर विचार करें।

#include <iostream> using namespace std; class A { public: virtual void f(); }; class B: public A { public: void f(); }; class C: public B { public: void f(); }; 

कौन सी कक्षाओं में वी-तालिका होगी?

चूंकि बी वर्चुअल के रूप में च () को नहीं घोषित करता है, क्या वर्ग सी गतिशील बहुरूपता प्राप्त करता है?

Solutions Collecting From Web of "सी ++ में बनाया गया एक वीटेल कब है?"

"Vtables कार्यान्वयन-विशिष्ट" से परे (जो वे हैं), यदि कोई vtable उपयोग किया जाता है: आपके प्रत्येक कक्षा के लिए अद्वितीय vtables होंगे भले ही B :: f और C :: F को वर्चुअल घोषित नहीं किया जाता है, क्योंकि बेस क्लास (आपके कोड में A ) से आभासी पद्धति पर एक मिलान के हस्ताक्षर हैं, B :: f और C :: F दोनों निहित वर्चुअल हैं । क्योंकि प्रत्येक वर्ग में कम से कम एक अद्वितीय आभासी पद्धति ( बी :: एफ ओवरराइड ए :: एफ के बी उदाहरण और सी :: एफ सी के उदाहरणों के लिए इसी तरह की है ), आपको तीन vtables की आवश्यकता है

आपको आम तौर पर ऐसे विवरणों के बारे में चिंता नहीं करनी चाहिए। क्या मायने रखता है कि क्या आपके पास आभासी प्रेषण है या नहीं आपको आभासी प्रेषण का उपयोग करने की ज़रूरत नहीं है, स्पष्ट रूप से निर्दिष्ट करने के लिए कि कौन सा फ़ंक्शन कॉल करता है, लेकिन आभासी पद्धति को कार्यान्वित करते समय यह आमतौर पर केवल उपयोगी होता है (जैसे कि बेस की विधि कॉल करना)। उदाहरण:

 struct B { virtual void f() {} virtual void g() {} }; struct D : B { virtual void f() { // would be implicitly virtual even if not declared virtual B::f(); // do D-specific stuff } virtual void g() {} }; int main() { { B b; bg(); bB::g(); // both call B::g } { D d; B& b = d; bg(); // calls D::g bB::g(); // calls B::g bD::g(); // not allowed dD::g(); // calls D::g void (B::*p)() = &B::g; (b.*p)(); // calls D::g // calls through a function pointer always use virtual dispatch // (if the pointed-to function is virtual) } return 0; } 

कुछ ठोस नियम जो मदद कर सकते हैं; लेकिन इन पर मुझे बोली न दें, मुझे कुछ बढ़त वाले मामलों की संभावना है:

  • अगर किसी कक्षा में आभासी विधियों या आभासी आधार हैं, भले ही विरासत में हो, तो उदाहरणों में एक vtable सूचक होना चाहिए।
  • यदि कोई वर्ग गैर-विरासत में आभासी विधियों की घोषणा करता है (जैसे कि उसमें कोई आधार वर्ग नहीं है), तो इसके पास अपने स्वयं के vtable होना चाहिए।
  • अगर किसी क्लास के पहले आधार वर्ग की तुलना में ओवरराइड करने के तरीकों का एक अलग सेट है, तो उसके पास अपना वीटेल होना चाहिए, और बेस का पुनः उपयोग नहीं कर सकते (डिस्ट्रक्टर्स को सामान्यतः इस आवश्यकता होती है।)
  • यदि एक क्लास में एकाधिक आधार वर्ग हैं, तो आभासी विधियों वाले दूसरे या बाद के आधार के साथ:
    • यदि कोई पहले के आधार पर आभासी तरीके नहीं हैं और खाली बेस अनुकूलन को सभी आधारभूत ठिकानों पर लागू किया गया है, तो इस बेस को पहले बेस क्लास के रूप में रखें।
    • अन्यथा, क्लास के पास अपना वीटेल होना चाहिए।
  • यदि किसी वर्ग में कोई आभासी मूल कक्षाएं हैं, तो इसके पास अपना वीटेल होना चाहिए

याद रखें कि एक वीटेल एक क्लास के एक स्थिर डेटा सदस्य के समान है, और उदाहरणों में इनके केवल संकेत हैं

इसके अलावा व्यापक लेख सी ++: अंडर द हूड (मार्च 1 99 4) जनवरी ग्रे द्वारा देखें। ( Google का प्रयास करें कि लिंक मर जाता है।)

Vtable का पुन: उपयोग करने का उदाहरण:

 struct B { virtual void f(); }; struct D : B { // does not override B::f // does not have other virtuals of its own void g(); // still might have its own non-virtuals int n; // and data members }; 

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

उत्तर है, यह निर्भर करता है'। यह 'vtbl में शामिल' से आपके द्वारा क्या मतलब है पर निर्भर करता है और यह विशेष संकलक के लागूकर्ता द्वारा किए गए निर्णयों पर निर्भर करता है।

सख्ती से बोलना, कोई 'कक्षा' कभी भी एक वर्चुअल फ़ंक्शन टेबल नहीं है कुछ कक्षाओं के कुछ उदाहरणों में आभासी फंक्शन तालिकाओं के लिए पॉइंटर्स होते हैं हालांकि, यह सिर्फ एक संभव सिमेंटिक कार्यान्वयन है।

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

यदि आप पूछते हैं, 'जीसीसी क्या करता है?' या 'विज़ुअल सी ++ क्या करता है?' तो आपको एक ठोस जवाब मिल सकता है।

@ हसन सय्यद का जवाब शायद आप के बारे में क्या पूछ रहे थे, इसके करीब है, लेकिन सीधे इस अवधारणा को रखने के लिए वास्तव में महत्वपूर्ण है।

व्यवहार (गतिशील डिस्पैच क्या कक्षा नया था पर आधारित है) और वहाँ कार्यान्वयन है आपके सवाल का इस्तेमाल कार्यान्वयन शब्दावली, हालांकि मुझे संदेह है कि आप एक व्यवहारिक उत्तर की तलाश कर रहे थे।

व्यवहार का उत्तर यह है: किसी भी वर्ग जो एक आभासी फ़ंक्शन को घोषित करता है या उसे विरासत में लेता है, उस फ़ंक्शन पर कॉल करने के लिए गतिशील व्यवहार प्रदर्शित करेगा। कोई भी वर्ग जो नहीं करता है, नहीं होगा

कार्यान्वयन-वार, संकलक को ऐसा करने की अनुमति है जो वह परिणाम पूरा करना चाहे।

उत्तर

एक वर्टेबल बनाया जाता है जब एक क्लास घोषणापत्र में वर्चुअल फंक्शन होता है। एक वीटेल पेश किया जाता है जब एक अभिभावक – कहीं भी उत्तराधिकार में – एक आभासी फ़ंक्शन है, इस माता पिता को कहें। वाई के किसी भी माता-पिता के पास वीटेल नहीं होगा (जब तक कि उनके पास उनके किसी अन्य कार्य के लिए virtual )।

चर्चा और परीक्षणों के लिए पढ़ें

– स्पष्टीकरण –

जब आप वर्चुअल के रूप में एक सदस्य फ़ंक्शन निर्दिष्ट करते हैं, तो एक मौका है कि आप रन-टाइम में बेस-क्लास पॉलिमोरफाईक के माध्यम से उप-कक्षाओं का उपयोग करने का प्रयास कर सकते हैं। भाषा डिजाइन पर प्रदर्शन की सी ++ की गारंटी बनाए रखने के लिए उन्होंने सबसे हल्का संभव क्रियान्वयन की रणनीति की पेशकश की – यानी, एक स्तर पर indirection, और केवल जब एक क्लास रनटाइम पर पॉलिमोरफाईक्स का इस्तेमाल किया जा सकता है, और प्रोग्रामर इसे कम से कम एक फ़ंक्शन सेट करके निर्दिष्ट करता है आभासी।

यदि आप वर्चुअल कीवर्ड से बचते हैं, तो आपको वीटेल की लागत नहीं होती है।

– संपादित करें: अपने संपादन को प्रतिबिंबित करने के लिए –

तभी जब कोई बेस क्लास में एक वर्चुअल फ़ंक्शन होता है, तो कोई अन्य उप-कक्षाओं में एक vtable होता है। माता-पिता ने कहा कि बेस क्लास में वीटेल नहीं है

आपके उदाहरण में सभी तीन वर्गों में एक वीटेल होगा, ऐसा इसलिए है क्योंकि आप सभी तीन वर्गों को A*. माध्यम से उपयोग करने का प्रयास कर सकते हैं A*.

– टेस्ट – जीसीसी 4+ –

 #include <iostream> class test_base { public: void x(){std::cout << "test_base" << "\n"; }; }; class test_sub : public test_base { public: virtual void x(){std::cout << "test_sub" << "\n"; } ; }; class test_subby : public test_sub { public: void x() { std::cout << "test_subby" << "\n"; } }; int main() { test_sub sub; test_base base; test_subby subby; test_sub * psub; test_base *pbase; test_subby * psubby; pbase = &sub; pbase->x(); psub = &subby; psub->x(); return 0; } 

उत्पादन

 test_base test_subby 

test_base में एक वर्चुअल टेबल नहीं है इसलिए इस पर जो कुछ भी test_base जाता है test_base से x() उपयोग करेगा दूसरी ओर test_sub x() की प्रकृति को बदलता है और इसका सूचक एक test_subby माध्यम से अप्रत्यक्ष होता है, और इसे test_subby के x() द्वारा निष्पादित किया जाता है।

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

आपने अपना प्रश्न बहुत स्पष्ट और सटीक बनाने का प्रयास किया, लेकिन अभी भी कुछ जानकारी गायब है। आप शायद जानते हैं, कि वी-टेबल का उपयोग करने वाले कार्यान्वयन में, तालिका आमतौर पर एक स्वतंत्र आंकड़ा संरचना होती है, जो बहुरूपिक वस्तुओं के बाहर संग्रहीत होती है, जबकि वस्तुएं खुद ही तालिका में एक निहित संकेतक संग्रह करती हैं। तो, आप क्या पूछ रहे हैं? हो सकता है:

  • किसी ऑब्जेक्ट को वी-टैबलेट में डालने के लिए एक निहित सूचक मिलता है?

या

  • पदानुक्रम में दिए गए प्रकार के लिए बनाया गया एक समर्पित, व्यक्तिगत वी-तालिका कब है?

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

दूसरे प्रश्न का उत्तर संभवतः पहला अपवाद (विकल्प 3) के समान हो सकता है। अगर एकल विरासत पदक्रम में कुछ बहुरूपिक वर्ग का अपना कोई आभासी कार्य नहीं होता (कोई नया वर्चुअल फ़ंक्शन नहीं, अभिभावकीय आभासी फ़ंक्शन के लिए कोई ओवरराइड नहीं), तो यह संभव है कि कार्यान्वयन इस वर्ग के लिए एक व्यक्तिगत वी-तालिका बनाने का निर्णय नहीं ले सकता, बल्कि इसके बजाय इस वर्ग के लिए तात्कालिक माता-पिता की वी-टेबल का प्रयोग करें (क्योंकि यह वही हो सकता है)। Ie इस मामले में मूल प्रकार और व्युत्पन्न प्रकार की वस्तुओं के दोनों ऑब्जेक्ट उनके एम्बेडेड V- तालिका पॉइंटर्स में समान मान संग्रहीत करेंगे यह, ज़ाहिर है, कार्यान्वयन पर अत्यधिक निर्भर है। मैंने जीसीसी और एमएस वीएस 2005 की जांच की और वे उस तरह से कार्य नहीं करते। वे दोनों इस स्थिति में व्युत्पन्न वर्ग के लिए एक व्यक्तिगत वी-तालिका बनाते हैं, लेकिन मुझे लगता है कि लागू नहीं करने वाले लोगों के बारे में सुनना याद है।

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

व्यवहार अध्याय 10.3, सी ++ भाषा विनिर्देश के अनुच्छेद 2 में परिभाषित किया गया है:

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

एक उपयुक्त वाक्यांश को अलग करना इस प्रकार, यदि आपका कंपाइलर वी-तालिकाओं को सामान्य अर्थों में बनाता है तो सभी कक्षाओं में एक v-table होगा क्योंकि उनके सभी एफ () विधियां आभासी हैं।