2015-06-25 5 views
5

क्या कोई भी C++ में निम्न कोड के आउटपुट के लिए सटीक कारण बता सकता है? कोड के लिए मुझे प्राप्त आउटपुट हेडर टिप्पणियों में शामिल किया गया है। वर्चुअल टेबल और वी पॉइंटर के साथ इसका क्या संबंध है।खाली कक्षाओं का उपयोग कर वर्चुअल विरासत

/* sizeof(Empty) 1                     
sizeof(Derived1) 1 
sizeof(Derived2) 8 
sizeof(Derived3) 1 
sizeof(Derived4) 16 
sizeof(Dummy) 1 
*/ 

#include <iostream> 
using namespace std; 

class Empty 
{}; 

class Derived1 : public Empty 
{}; 

class Derived2 : virtual public Empty 
{}; 

class Derived3 : public Empty 
{  
char c; 
}; 

class Derived4 : virtual public Empty 
{ 
char c; 
}; 

class Dummy 
{ 
char c; 
}; 

int main() 
{ 

    cout << "sizeof(Empty) " << sizeof(Empty) << endl; 
    cout << "sizeof(Derived1) " << sizeof(Derived1) << endl; 
    cout << "sizeof(Derived2) " << sizeof(Derived2) << endl; 
    cout << "sizeof(Derived3) " << sizeof(Derived3) << endl; 
    cout << "sizeof(Derived4) " << sizeof(Derived4) << endl;  
    cout << "sizeof(Dummy) " << sizeof(Dummy) << endl; 
    return 0; 

} 
+0

[आउटपुट पर आउटपुट थोड़ा अलग है] (http://ideone.com/1PZ8b4) [हालांकि, coliru के माध्यम से g ++ आपके साथ सहमत है] (http://coliru.stacked-crooked.com/a/2bc0dc89c3fb717f) – AndyG

+1

यहां देखें http://stackoverflow.com/questions/3972548/virtual-dispatch-implementation- विवरण – user2079303

+0

@ Rndp13: कृपया सब कुछ के लिए अप्रासंगिक और बेकार टैग जोड़ने को रोकें। –

उत्तर

3

सबसे पहले, यहां तक ​​कि किसी भी सदस्य के साथ कक्षा में गैर-शून्य आकार होना चाहिए। मानक उस पर जोर देता है। अन्यथा पॉइंटर अंकगणितीय और सरणी शून्य आकार के वर्ग की सरणी के रूप में काम नहीं करेंगे, इसके सभी तत्व एक ही स्थान पर होंगे!

तथ्य यह है कि अन्य आकार भिन्न होते हैं, वे एक वी-टेबल के कारण हो सकते हैं। लेकिन यह मानक में स्पष्ट रूप से अनिवार्य नहीं है, इसलिए आपके कंपाइलर चीजों से निपटने के तरीके का एक अभिव्यक्ति है।

ध्यान दें कि बहुरूपता को आधार वर्ग में परिभाषित करने के लिए कम से कम एक वर्चुअल विधि की आवश्यकता होती है। यह sizeof(Derived1) के लिए आधार वर्ग के समान आकार के लिए खाता है।

+0

क्या इस मामले में मानक अनुपालन को बनाए रखने के दौरान वी-टेबल छोड़ा जा सकता है?दूसरे शब्दों में, क्या संकलक 'आभासी' विरासत को अनदेखा कर सकता है, क्योंकि आधार वर्ग में कोई फ़ील्ड और न ही वर्चुअल विधियां हैं? – chi

1

आकार में अंतर vptr संकलक द्वारा जोड़ा गया है।

sizeof(Derived1) = 1, ऐसा इसलिए है क्योंकि सी ++ मानकों के अनुसार खाली कक्षा हमेशा स्मृति के 1 बाइट पर कब्जा करती है।

sizeof(Derived2) = 8, चूंकि यह आभासी आधार वर्ग Derived1 इनहेरिट करती है, तो एक vptr संकलक (sizeof(vptr) = 8 एक 64 बिट मशीन पर) और इसलिए sizeof(Derived2) 8 बाइट्स दिखा रहा है द्वारा जोड़ा जाता है।

sizeof(Derived3) = 1char के 1 बाइट के कारण।

sizeof(Derived4) = 16, वर्चुअल विरासत का आंतरिक कार्यान्वयन पूरी तरह से संकलक पर निर्भर है, इस कारण आप आकार के रूप में 16 बाइट्स देख रहे हैं।

sizeof(Dummy) = 1 चूंकि इसमें एक एकल इकाई इकाई है।

1

Empty आकार 1 है, क्योंकि हर वस्तु कम से कम 1.

Derived1 के आकार होना आवश्यक है इसी कारण से आकार 1 है।

Derived2 आकार 8 है क्योंकि आपके कंपाइलर को वर्चुअल विरासत (शायद एक सूचक) के लिए 8 बाइट की आवश्यकता है।

Derived3 आकार 1 है क्योंकि आपके कंपाइलर ने "खाली बेस क्लास" अनुकूलन लागू किया है।

Derived4 आकार 16 है क्योंकि वर्चुअल विरासत के लिए आवश्यक 8 बाइट्स को ऑब्जेक्ट को 8-बाइट संरेखण की आवश्यकता होती है।

Dummy आकार 1 है क्योंकि यह char का आकार है।

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