से प्राप्त करने से रोकें मैं समस्या का वर्णन करने के लिए उचित प्रश्न शीर्षक के बारे में नहीं सोच सकता। उम्मीद है कि नीचे दिए गए विवरण मेरी समस्या को स्पष्ट करते हैं।उपयोगकर्ता को गलत सीआरटीपी बेस
निम्नलिखित कोड
#include <iostream>
template <typename Derived>
class Base
{
public :
void call()
{
static_cast<Derived *>(this)->call_impl();
}
};
class D1 : public Base<D1>
{
public :
void call_impl()
{
data_ = 100;
std::cout << data_ << std::endl;
}
private :
int data_;
};
class D2 : public Base<D1> // This is wrong by intension
{
public :
void call_impl()
{
std::cout << data_ << std::endl;
}
private :
int data_;
};
int main()
{
D2 d2;
d2.call_impl();
d2.call();
d2.call_impl();
}
यह संकलन और चलाने हालांकि D2
की परिभाषा जानबूझकर गलत है पर विचार करें। पहला कॉल d2.call_impl()
कुछ यादृच्छिक बिट्स आउटपुट करेगा जो D2::data_
के रूप में अपेक्षित नहीं थे। दूसरी और तीसरी कॉल data_
के लिए सभी 100
आउटपुट करेंगे।
मुझे समझ में आता है कि यह क्यों संकलित और चलाएगा, अगर मैं गलत हूं तो मुझे सही करें।
जब हम कॉल d2.call()
बनाने के लिए, कॉल Base<D1>::call
को हल हो गई है, और कहा कि D1
को this
डाली और D1::call_impl
कॉल करेंगे। क्योंकि D1
वास्तव में Base<D1>
रूप से निकाला गया है, इसलिए कास्ट संकलन समय पर ठीक है।
, कलाकारों के बाद, this
, यह वास्तव में एक D2
वस्तु व्यवहार किया जाता है, जबकि के रूप में अगर यह D1
है, और D1::call_impl
इच्छा के कॉल स्मृति बिट्स कि D1::data_
, और उत्पादन होने की अपेक्षा की जाती है संशोधित। इस मामले में, ये बिट्स D2::data_
हैं। मुझे लगता है कि दूसरा d2.call_impl()
सी ++ कार्यान्वयन के आधार पर अपरिभाषित व्यवहार भी होगा।
बिंदु यह है कि, यह कोड, जबकि गहन रूप से गलत है, उपयोगकर्ता को त्रुटि का कोई संकेत नहीं देगा। मैं वास्तव में अपनी परियोजना में क्या कर रहा हूं कि मेरे पास एक सीआरटीपी बेस क्लास है जो एक प्रेषण इंजन की तरह कार्य करता है। लाइब्रेरी में एक और वर्ग सीआरटीपी बेस क्लास इंटरफ़ेस तक पहुंचता है, call
कहता है, और call
call_dispatch
पर प्रेषित होगा जो बेस क्लास डिफ़ॉल्ट कार्यान्वयन या व्युत्पन्न क्लास कार्यान्वयन हो सकता है। यदि उपयोगकर्ता व्युत्पन्न कक्षा को परिभाषित करते हैं, तो D
कहें, ये सभी ठीक काम करेंगे, वास्तव में Base<D>
से प्राप्त किए गए हैं। यह संकलन समय त्रुटि को बढ़ाएगा यदि यह Base<Unrelated>
से लिया गया है जहां Unrelated
Base<Unrelated>
से नहीं लिया गया है। लेकिन यह उपरोक्त की तरह उपयोगकर्ता लिखने कोड को नहीं रोकेगा।
उपयोगकर्ता आधार सीआरटीपी कक्षा से प्राप्त करके पुस्तकालय का उपयोग करते हैं और कुछ कार्यान्वयन विवरण प्रदान करते हैं। निश्चित रूप से अन्य डिज़ाइन विकल्प हैं जो उपरोक्त के रूप में गलत उपयोग की समस्या से बच सकते हैं (उदाहरण के लिए एक सार आधार वर्ग)। लेकिन चलो अब उन्हें एक तरफ रख दें और सिर्फ मुझे विश्वास करें कि किसी कारण से मुझे इस डिजाइन की ज़रूरत है।
तो मेरा सवाल यह है कि, क्या कोई तरीका है कि मैं उपयोगकर्ता को उपरोक्त के रूप में गलत व्युत्पन्न कक्षा लिखने से रोक सकता हूं। यही है, यदि उपयोगकर्ता व्युत्पन्न कार्यान्वयन वर्ग लिखते हैं, तो D
कहें, लेकिन उन्होंने इसे Base<OtherD>
से लिया, फिर संकलन समय त्रुटि उठाई जाएगी।
एक समाधान dynamic_cast
का उपयोग किया जाता है। हालांकि, यह विशाल है और यहां तक कि जब यह काम करता है यह एक रन-टाइम त्रुटि है।
संक्षिप्त उत्तर: नहीं। 'dynamic_cast' महंगा हो सकता है, लेकिन यह आपके उपयोगकर्ताओं को ठीक करने की कोशिश करने से सस्ता है। – Rook
कम से कम असफल गतिशील_कास्ट यूनिट परीक्षणों में तेजी से मिलेगा। आप संकलक, हर संभव टाइपो से बचाने 'लेखन मैं 1' + जब' अर्थ मैं की तरह नहीं हो सकता है - 1'। यह समान है। –
संभावित डुप्लिकेट [सीआरटीपी का उपयोग करते समय त्रुटियों से कैसे बचें?] (Http://stackoverflow.com/questions/4417782/how-to-avoid-errors-while-using-crtp) –