2010-01-31 15 views
19

मैंने बहुत से लोगों को पढ़ा है "एक वर्चुअल टेबल उस वर्ग के लिए मौजूद है जिसमें वर्चुअल फ़ंक्शन घोषित किया गया है"।वर्चुअल टेबल सी ++

मेरा प्रश्न है, क्या एक vtable केवल उस वर्ग के लिए मौजूद है जिसमें वर्चुअल फ़ंक्शन है या यह उस वर्ग से प्राप्त कक्षाओं के लिए भी मौजूद है।

, उदा,

class Base{ 
    public: 
     virtual void print(){cout<<"Base Print\n";} 
}; 
class Derived:public Base{ 
    public: 
     void print(){cout<<"Derived print\n";} 
}; 

//From main.cpp 
Base* b = new Derived; 
b->print(); 

प्रश्न: ली गई तो उत्पादन नहीं किया गया होगा "व्युत्पन्न प्रिंट" वर्ग के लिए कोई vtable वहाँ गया था। तो आईएमओ किसी भी वर्ग के लिए एक vtable मौजूद है जिसमें वर्चुअल फ़ंक्शन घोषित किया गया है और उस वर्ग से विरासत में प्राप्त कक्षाओं में भी। क्या ये सही है ?

+2

प्रयोग को पूरा करने के लिए, क्लास व्युत्पन्न 2 बनाएं जो व्युत्पन्न से प्राप्त होता है और प्रिंट को ओवरराइड करता है। आधार पर पॉइंटर के माध्यम से इस तरह के एक उदाहरण पर प्रिंट प्रिंट करें ... – VoidPointer

+2

लिंक के नीचे Vtable @ के बारे में और जानें: http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/ –

उत्तर

19

जहां तक ​​केवल आभासी-समारोह-विशिष्ट कार्यक्षमता कार्यान्वयन व्युत्पन्न वर्ग vtable को vtable का एक अलग संस्करण की आवश्यकता होगी एक परंपरागत दृष्टिकोण में माना जाता है, अगर और केवल जो व्युत्पन्न वर्ग कम से कम एक वर्चुअल फ़ंक्शन ओवरराइड करता है। आपके उदाहरण में, Derived वर्चुअल फ़ंक्शन print ओवरराइड करता है। चूंकि Derived का अपना संस्करण print है, Derived vtable में इसी प्रविष्टि Base vtable से अलग है। यह आमतौर पर Derived के लिए एक अलग vtable की आवश्यकता होगी।

हैं Derived सब पर कुछ भी ओवरराइड नहीं किया, औपचारिक रूप से यह अभी भी एक अलग बहुरूपी वर्ग होगा, लेकिन इसकी आभासी कार्यों के रूप में अच्छी तरह से Derived के लिए काम ठीक से हम केवल पुन: उपयोग किया जा सकता था Base vtable बनाने के लिए। इसलिए, तकनीकी रूप से Derived के लिए एक अलग vtable की आवश्यकता नहीं होगी।

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

+1

@AndreyT: क्या आप कुछ वेबपृष्ठ के बारे में जानते हैं जो सी ++ के लिए शुरुआती तरीके से 'vtable' से संबंधित अवधारणाओं को समझाता है? मैं यह समझने की कोशिश कर रहा हूं कि एक vtable की आवश्यकता क्यों है, और यह वास्तव में कैसे कार्यान्वित किया जाता है। – Lazer

+0

@ लाज़र कार्यान्वयन विवरण अनिर्दिष्ट हैं। तालिका को रनटाइम पर आवश्यक है, सिस्टम को यह पता है कि एक पॉलिमॉर्फिक फ़ंक्शन का कौन सा संस्करण कॉल करने के लिए (इसे संकलित समय पर निर्धारित नहीं किया जा सकता है; बेस-क्लास पॉइंटर पर एक ऑपरेशन पर विचार करें - यदि पॉइंटर एक उदाहरण के लिए इंगित करता है तो ऑपरेशन अलग हो सकता है व्युत्पन्न वर्ग या बेस क्लास का उदाहरण)। Https://en.wikipedia.org/wiki/Virtual_method_table देखें – RJFalconer

2

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

लेकिन ध्यान रखें कि 'vtable' की अवधारणा सामान्य रूप से प्रत्येक कंपाइलर द्वारा उपयोग की जाने वाली सामान्य प्रथा है, लेकिन यह अनिवार्य नहीं है और न ही मानकीकृत है।

+0

vtable है सदस्य या किसी सदस्य की तरह कुछ भी नहीं। क्या आपका मतलब वीपीआरआर है? – curiousguy

3

हां, आपकी समझ सही है। किसी भी वर्चुअल फ़ंक्शंस के साथ आधार वाला कोई वर्ग एक vtable है।

3

हाँ यह सच है। असल में, यह देखते हुए इस सैन्य अड्डे का defintion:

class derived:public base{ 
public: 
virtual void print(){cout<<"derived print\n";} 
}; 

क्योंकि आप पहले से आधार में आभासी के रूप में प्रिंट में परिभाषित किया गया ...:

class derived:public base{ 
public: 
void print(){cout<<"derived print\n";} 
}; 

पूरी तरह से करने के लिए बराबर है।

काश था संकलक कि लागू होगा ...

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