2011-02-10 27 views
14

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

तो एक सुरक्षित स्पष्ट कलाकार क्यों नहीं है? यहां एक उदाहरण दिया गया है, जहां यह उपयोगी हो सकता है। कॉम में, वे void** ppv के रूप में इंटरफ़ेस सूचक वापस जाने के लिए है, तो एक सुरक्षित सी ++

*ppv = static_cast<IInterface*>(this); 

डाली लेकिन यह पड़ता है द्वारा डाली पर स्पष्ट रूप

*ppv = (IInterface*) this; 

जो तब सुझाव दिया गया था बदला जाएगा "करने के लिए है" यहां तक ​​कि static_cast भी बनाने की भावना है? this, एक वर्ग जो IInterface से निकला की है, इसलिए एक बस

IInterface* p = this; // implicit conversion to base, safe for sure 
*ppv = p; 

लिख सकते हैं या

template<class T, class U> 
T implicit_cast(U p) { return p; } 

*ppv = implicit_cast<IInterface*>(this); 

तो जैसे एक सहायक इस्तेमाल कर सकते हैं, यह सच है कि static_cast कभी कभी दुरुपयोग किया जाता है और यह कर सकते हैं है (होना चाहिए?) कुछ मामलों में इस implicit_cast द्वारा प्रतिस्थापित किया जा सकता है, या क्या मुझे कुछ याद आ रही है?

संपादित करें: मुझे पता है कि a cast is required in COM, लेकिन यह static_cast होना आवश्यक नहीं है, एक निहित कास्ट पर्याप्त होगा।

+1

नोट: 'implicit_cast' (और एक अच्छा स्पष्टीकरण) के" सही "कार्यान्वयन के लिए http://stackoverflow.com/a/869597 देखें। –

उत्तर

5

इस विशेष मामले में मेरा मानना ​​है कि यह हमेशा ज्ञात है कि कास्टिंग ऊपर की ओर होगा और इसलिए static_cast पूरी तरह से सुरक्षित होना चाहिए।

ऐसा लगता है कि आपके implicit_cast का उपयोग संभवतः सुरक्षित होगा, और आपको स्पष्ट रूप से यह चुनने की अनुमति देता है कि आप कौन सी बेस क्लास को निहित रूप से डालना चाहते हैं (जो स्पष्ट रूप से COM के लिए आवश्यक है)।

मैंने जी ++ और implicit_cast के साथ त्वरित परीक्षण किया है, वास्तव में अपेक्षाकृत विभिन्न आधार वर्गों के लिए अलग-अलग पते लौटाता है।

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

टेस्ट कार्यक्रम:

#include <iostream> 

class B1 
{ 
public: 
    virtual ~B1() {} 
}; 

class B2 
{ 
public: 
    virtual ~B2() {} 
}; 

class Foo : public B1, public B2 
{ 
}; 

template<class T, class U> 
T implicit_cast(U p) { return p; } 

int main() 
{ 
    Foo* f = new Foo; 
    void **ppv = new void*; 

    *ppv = implicit_cast<B1*>(f); 
    std::cout << *ppv << std::endl;; 
    *ppv = implicit_cast<B2*>(f); 
    std::cout << *ppv << std::endl;; 

    return 0; 
} 
+0

वास्तव में, 'dynamic_cast'' static_cast' से सुरक्षित होगा लेकिन मैंने इसका उल्लेख नहीं किया क्योंकि मैंने इसे वास्तव में कभी नहीं देखा है (मैंने प्रदर्शन प्रदर्शन के बारे में सुना है लेकिन यह नहीं पता कि यह कितना बड़ा है)। –

+2

@ 7vies: विज़ुअल सी ++ में यह लगभग 2 हजार प्रोसेसर चक्र है और यदि आप अपनी COM ऑब्जेक्ट को गलत प्रकार पर डालते हैं तो संकलक आपको नहीं पकड़ पाएगा - आपको केवल रनटाइम के दौरान एक शून्य सूचक मिलेगा। – sharptooth

+0

@ शार्पतोथ: हाँ, 'गतिशील_कास्ट 'निश्चित रूप से COM संदर्भ में सबसे अच्छा विकल्प नहीं है। मुझे यह भी यकीन नहीं है कि किस स्थिति में यह एक अच्छा विकल्प हो सकता है - ज्यादातर मामलों में इसे रन-टाइम या संकलन-समय पॉलीमोर्फिज्म द्वारा प्रतिस्थापित किया जा सकता है जो एक ही समय में सुरक्षित और तेज़ होगा। –

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