c++ अमूर्त आधार वर्गों पर__declspec(novitable) का उपयोग किसी भी तरह से आरटीटीआई को प्रभावित करता है?




visual-studio visual-c++ (2)

या, क्या __declspec (novitable) को नियोजित करने के लिए कोई अन्य ज्ञात नकारात्मक प्रभाव होता है? मुझे किसी भी मुद्दे के संदर्भ नहीं मिल सकता है


अगर मैं इसे सही ढंग से समझता हूं: किसी भी आभासी एफएन कॉल को एक सीटीओआर या एक डीटीओआर के अंदर जोड़ने के लिए कम्बल टाइम लिंक में कनवर्ट किया जाता है। हम (सी / डी) टॉर्स से आभासी एफएन कॉल्स नहीं कर सकते इसका कारण यह है कि जब बेस क्लास का ऑब्जेक्ट तैयार हो रहा है, तो उसे व्युत्पन्न वर्ग का कोई ज्ञान नहीं है और इसलिए वह व्युत्पन्न क्लास को कॉल नहीं कर सकता है और डीटीओआर एक ही तर्क लागू होता है।


एमएससीवी ओटीओ तंत्र को कार्यान्वित करने जैसे one vptr per object and one vtbl per class और वर्चुअल फ़ंक्शंस को लागू करने के लिए one vptr per object and one vtbl per class वीटीबी का उपयोग करता है।
इसलिए आरटीटीआई और वर्चुअल फ़ंक्शन ठीक काम करेगा अगर केवल अगर vptr को सही ढंग से सेट किया गया हो

struct __declspec(novtable) B {
    virtual void f() = 0;
};
struct D1 : B {
    D1() {
    }       // after the construction of D1, vptr will be set to vtbl of D1.
};
D1 d1;      // after d has been fully constructed, vptr is correct.
B& b = d1;  // so virtual functions and RTTI will work.
b.f();      // calls D1::f();
assert( dynamic_cast<D1*>(&b) );
assert( typeid(b) == typeid(D1) );

बी __declspec(novtable) उपयोग करते समय बी एक सार वर्ग होना चाहिए
डी के कन्स्ट्रक्टर को छोड़कर बी की कोई घटना नहीं होगी I
और __declspec (novtable) के अधिकांश मामले में कोई नकारात्मक प्रभाव नहीं पड़ता है।

लेकिन व्युत्पन्न वर्ग __declspec(novtable) के निर्माण के दौरान आईएसओ सी ++ अर्थ से अलग होगा।

struct D2 : B {


    D2() {  // when enter the constructor of D2 \  
            //     the vtpr must be set to vptr of B \
            //     if  B didn't use __declspec(novtable).
            // virtual functions and RTTI will also work.

            this->f(); // should calls B::f();
            assert( typeid(*this) == typeid(B) );
            assert( !dynamic_cast<D2*>(this) );
            assert( dynamic_cast<B*>(this) );

            // but __declspec(novtable) will stop the compiler \
            //    from generating code to initialize the vptr.
            // so the code above will crash because of uninitialized vptr.
    }
};

नोट: आभासी एफ () = 0 ; एक pure virtual function बनने के लिए च बनाता है और बी एक सार वर्ग बनने के लिए।
एक शुद्ध आभासी फ़ंक्शन की definition ( must ) गायब हो सकती है।
सी ++ कन्स्ट्रक्टर में आभासी फ़ंक्शन कॉल की अनुमति देता है जिसे हम अनुशंसा नहीं करते हैं

अद्यतन: डी 2 में एक गलती: व्युत्पन्न कन्स्ट्रक्टर में वीपीटीआर।

struct D3 : B {  // ISO C++ semantic
    D3() {       // vptr must be set to vtbl of B before enter
    }            // vptr must be set to vtbl of D2 after leave
};

लेकिन वीपीटीआर निर्माण के दौरान अनिश्चित है। यह एक कारण है कि कन्स्ट्रक्टर में वर्चुअल फंक्शन कॉल की सिफारिश नहीं है।

अगर डी 2 :: डी 2 () में वीपीटीआर बी थी और बी :: एफ () की परिभाषा गायब थी, तो this->f(); vtbl में जब dereference पॉइंटर-टू-फ़ंक्शन को क्रैश हो जाएगा।
अगर डी 2 :: डी 2 () में वीपीटीआर बी और बी का उपयोग करें, तो यह- this->f(); दुर्घटना तब होगी, जब कोई अप्रतिभूतित vptr

वास्तव में, डी 2 :: डी 2 () में वीपीटीआर एमएसवीसी (एमएसवीसी 8) में डी 2 है। डी 2 :: डी 2 () में दूसरे कोड को निष्पादित करने से पहले डी 2 के लिए संकलक सेट vptr।
तो this->f(); कॉल D2 :: f () और तीन अभियुक्तों का उल्लंघन होगा।





compiler-specific