2017-05-24 5 views
5

मैं आभासी तालिका और विरासत के साथ कुछ निम्न-स्तर की चीज़ों को कम करने की कोशिश कर रहा हूं।व्युत्पन्न कक्षाओं में vtable की समझ

जब आप दो कक्षाओं को विरासत में जोड़कर और नए आभासी कार्यों को जोड़कर नई कक्षा बनाते हैं, जहां वास्तव में वीपीआरआर संग्रहीत किया जाएगा?

ऐसा लगता है कि संकलक उस मामले में कुछ 'vptr-optimization' करता है। और मैं इसे समझने की कोशिश कर रहा हूं।

मान लीजिए, हम निम्नलिखित structs है:

struct A 
{ 
    int a; 
    virtual void fa(); 
}; 
struct B 
{ 
    double b; 
    virtual void fb(); 
}; 
struct C : A, B 
{ 
    char c; 
    virtual void fa(); 
    virtual void fb(); 
    virtual void fc(); 
}; 

86 के मामले में और align = 4, A और B स्मृति में इस तरह दिखेगा:

+------+------+ 
A: | vptr | a | 
    +------+------+ 
sizeof(A) = 4 + 4 = 8 

    +------+------+------+------+ 
B: | vptr  |  b  | 
    +------+------+------+------+ 
sizeof(B) = 8 + 8 = 16 

लेकिन जब मैं करने की कोशिश C reassemble, मुझे यह मिलता है:

+------+------+------+------+------+------+------+ 
C: | vptr | a | vptr  |  b  | c | 
    +------+------+------+------+------+------+------+ 
but sizeof(C) = 32 

С с; 
(C*)&c; // 0x100 
(B*)&c; // 0x108 
(A*)&c; // 0x100 
&c.a; // 0x104 
&c.b; // 0x110 
&c.c; // 0x118 

तो whe फिर C का vptr है? मुझे लगता है कि कर सकते हैं कि संकलक विलय अलग आभासी टेबल, लेकिन इस मामले में क्यों sizeof(C) रिटर्न sizeof(A) + sizeof(B) + sizeof(alligned_char) + sizeof (vptr)

struct D : public C {} एक ही कहानी है (पूर्व A की vptr और C।) - वहाँ D का कोई vptr नहीं है।

मैं जिस कंपाइलर का उपयोग करता हूं वह msvc 2012 x86 है।

+1

क्यों struct बी की जरूरत 8 बाइट में vptr? – walker

+1

@ वाकर मुझे संदेह है कि यह करता है। यह शायद कुछ पैडिंग है। – luk32

+3

संभावित डुप्लिकेट [कितने vptr कक्षा का ऑब्जेक्ट (एकल/एकाधिक विरासत का उपयोग करता है) है?] (Https://stackoverflow.com/questions/3342035/how-many-vptr-will-a-object-of- क्लासस-सिंगल-बहु-विरासत-पास है) – Andrew

उत्तर

4

कंपाइलर को सादगी को जोड़ना है, इस तथ्य के साथ कि मूल कक्षाओं को वस्तु के भीतर मौजूद होना आवश्यक है।

+------+---------+----+ 
| A | B  | C | 
+------+---------+----+ 

तो

  • एक अस्तित्व के लिए जैसे कि वह प्राप्त नहीं किया गया था की जरूरत है।
  • बी को अस्तित्व में रहने की आवश्यकता है जैसे कि यह व्युत्पन्न नहीं हुआ था।
  • सी की नई स्वतंत्रता है।

ए और बी से वर्चुअल फ़ंक्शंस व्युत्पन्न कक्षा सी के कार्यान्वयन के लिए पैच किए जाएंगे। सी वर्चुअल फ़ंक्शंस (संभवतः) मौजूदा पहले तत्व A s vtable में जोड़ देगा।

आधार व्युत्पन्न वर्ग में A के लिए एक

+------+ 
| A:fa | 
+------+ 

vtable के लिए vtable व्युत्पन्न वर्ग में B के लिए C

+------+ 
| C:fa | // implemented by derived class. 
+------+ 
| C:fb | // any calls to fb need to be sent to `C`'s implementation 
+------+ 
| C:fc | // any calls to fc can be overridden by vtable. 
+------+ 

vtable C

+------+ 
| C:fb | // overridden, but no need to add fc, fa to this table. 
+------+ 

मुझे लगता है कि संरेखण नियम हैं causi C का आकार पैड किए जाने के लिए ताकि संरेखण संवेदनशील डबल सही ढंग से गठबंधन हो (सुनिश्चित करें कि C की सरणी ठीक तरह से गठबंधन है)।

B के आकार double गठबंधन है (4) और double के आकार सुनिश्चित करने के लिए vptr (4) और गद्दी के आकार है (8)

+1

के बारे में उल्लेख किया है, हाँ, यह केवल संरेखण नहीं हुआ, न कि एक नया vptr। – renzo

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