लगभग हर सी ++ संसाधन मैंने देखा है कि इस तरह की चर्चा करने से मुझे पता चलता है कि मुझे आरटीटीआई (रन-टाइम प्रकार की पहचान) का उपयोग करने के लिए बहुरूपी दृष्टिकोण पसंद करना चाहिए। सामान्य तौर पर, मैं इस तरह की सलाह को गंभीरता से लेता हूं, और औचित्य को समझने और समझने की कोशिश करूंगा - आखिरकार, C ++ एक शक्तिशाली जानवर है और इसकी पूरी गहराई को समझना कठिन है। हालाँकि, इस विशेष प्रश्न के लिए, मैं एक रिक्त चित्र बना रहा हूं और यह देखना चाहूंगा कि इंटरनेट किस तरह की सलाह दे सकता है। सबसे पहले, मुझे संक्षेप में बताएं कि मैंने अब तक क्या सीखा है, सामान्य कारणों को सूचीबद्ध करके कि आरटीटीआई को "हानिकारक क्यों माना जाता है":
कुछ संकलक इसका उपयोग नहीं करते / RTTI हमेशा सक्षम नहीं होता है
मैं वास्तव में इस तर्क को नहीं खरीदता। यह कहने की तरह है कि मुझे C ++ 14 सुविधाओं का उपयोग नहीं करना चाहिए, क्योंकि वहाँ बाहर संकलक हैं जो इसका समर्थन नहीं करते हैं। और फिर भी, कोई भी मुझे C ++ 14 सुविधाओं का उपयोग करने से हतोत्साहित नहीं करेगा। अधिकांश प्रोजेक्ट्स का उपयोग करने वाले कंपाइलर पर प्रभाव पड़ेगा, और यह कैसे कॉन्फ़िगर किया गया है। यहां तक कि जीसीसी मैनपेज को उद्धृत करते हुए:
-fno-rtti
C ++ रन-टाइम प्रकार पहचान सुविधाओं (डायनेमिक_कास्ट और टाइपिड) द्वारा उपयोग के लिए वर्चुअल फ़ंक्शंस के साथ हर वर्ग के बारे में जानकारी के अक्षम पीढ़ी। यदि आप भाषा के उन हिस्सों का उपयोग नहीं करते हैं, तो आप इस ध्वज का उपयोग करके कुछ स्थान बचा सकते हैं। ध्यान दें कि अपवाद हैंडलिंग समान जानकारी का उपयोग करता है, लेकिन G ++ इसे आवश्यकतानुसार उत्पन्न करता है। डायनामिक_कास्ट ऑपरेटर का उपयोग अभी भी उन जातियों के लिए किया जा सकता है जिन्हें रन-टाइम प्रकार की जानकारी की आवश्यकता नहीं है, अर्थात "शून्य *" या असंदिग्ध आधार वर्गों के लिए जाती हैं।
यह मुझे बताता है कि अगर मैं आरटीटीआई का उपयोग नहीं कर रहा हूं, तो मैं इसे अक्षम कर सकता हूं। यदि आप बूस्ट का उपयोग नहीं कर रहे हैं तो यह कहना पसंद है, आपको इसे लिंक करने की आवश्यकता नहीं है। मुझे उस मामले के लिए योजना बनाने की ज़रूरत नहीं है जहां कोई व्यक्ति संकलन कर रहा है -fno-rtti
। साथ ही, कंपाइलर इस मामले में जोर से और स्पष्ट रूप से विफल हो जाएगा।
इसमें अतिरिक्त मेमोरी खर्च होती है / यह धीमी हो सकती है
जब भी मुझे आरटीटीआई का उपयोग करने के लिए लुभाया जाता है, तो इसका मतलब है कि मुझे अपनी कक्षा के कुछ प्रकार की जानकारी या लक्षणों का उपयोग करने की आवश्यकता है। यदि मैं एक समाधान लागू करता हूं जो RTTI का उपयोग नहीं करता है, तो इसका आमतौर पर मतलब है कि मुझे इस जानकारी को संग्रहीत करने के लिए अपनी कक्षाओं में कुछ क्षेत्रों को जोड़ना होगा, इसलिए मेमोरी तर्क शून्य है (मैं आगे इस का एक उदाहरण दूंगा)।
एक डायनामिक_कास्ट धीमा हो सकता है, वास्तव में। हालांकि आमतौर पर इसे गति-गंभीर स्थितियों का उपयोग करने से बचने के तरीके हैं। और मैं विकल्प नहीं देखता। यह SO उत्तर , प्रकार को संग्रहीत करने के लिए आधार वर्ग में परिभाषित एक एनुम का उपयोग करने का सुझाव देता है। यह तभी काम करता है जब आप अपने सभी व्युत्पन्न वर्गों को प्राथमिकता देते हैं। वह काफी बड़ा "अगर" है!
उस जवाब से, यह भी लगता है कि आरटीटीआई की लागत स्पष्ट नहीं है, या तो। अलग-अलग लोग अलग-अलग चीजें मापते हैं।
सुरुचिपूर्ण बहुरूपी डिजाइन RTTI को अनावश्यक बना देंगे
इस तरह की सलाह मैं गंभीरता से लेता हूं। इस मामले में, मैं केवल अच्छे गैर-आरटीटीआई समाधान के साथ नहीं आ सकता हूं जो मेरे आरटीटीआई उपयोग के मामले को कवर करते हैं। मुझे एक उदाहरण प्रदान करें:
कहते हैं कि मैं कुछ प्रकार की वस्तुओं के ग्राफ़ को संभालने के लिए एक पुस्तकालय लिख रहा हूं। मैं अपने पुस्तकालय का उपयोग करते समय उपयोगकर्ताओं को अपने स्वयं के प्रकार उत्पन्न करने की अनुमति देना चाहता हूं (इसलिए एनम विधि उपलब्ध नहीं है)। मेरे पास अपने नोड के लिए एक बेस क्लास है:
class node_base
{
public:
node_base();
virtual ~node_base();
std::vector< std::shared_ptr<node_base> > get_adjacent_nodes();
};
अब, मेरे नोड विभिन्न प्रकार के हो सकते हैं। इनके बारे में क्या ख्याल है:
class red_node : virtual public node_base
{
public:
red_node();
virtual ~red_node();
void get_redness();
};
class yellow_node : virtual public node_base
{
public:
yellow_node();
virtual ~yellow_node();
void set_yellowness(int);
};
नरक, इनमें से एक भी क्यों नहीं:
class orange_node : public red_node, public yellow_node
{
public:
orange_node();
virtual ~orange_node();
void poke();
void poke_adjacent_oranges();
};
अंतिम समारोह दिलचस्प है। यहाँ इसे लिखने का एक तरीका दिया गया है:
void orange_node::poke_adjacent_oranges()
{
auto adj_nodes = get_adjacent_nodes();
foreach(auto node, adj_nodes) {
// In this case, typeid() and static_cast might be faster
std::shared_ptr<orange_node> o_node = dynamic_cast<orange_node>(node);
if (o_node) {
o_node->poke();
}
}
}
यह सब स्पष्ट और साफ लगता है। मुझे उन विशेषताओं या विधियों को परिभाषित करने की आवश्यकता नहीं है जहाँ मुझे उनकी आवश्यकता नहीं है, बेस नोड वर्ग दुबला और क्षुद्र रह सकता है। RTTI के बिना, मैं कहाँ से शुरू करूँ? हो सकता है कि मैं एक base_type विशेषता को आधार वर्ग में जोड़ सकूँ:
class node_base
{
public:
node_base();
virtual ~node_base();
std::vector< std::shared_ptr<node_base> > get_adjacent_nodes();
private:
std::string my_type;
};
क्या std :: स्ट्रिंग एक प्रकार के लिए एक अच्छा विचार है? शायद नहीं, लेकिन मैं और क्या उपयोग कर सकता हूं? एक संख्या बनाएं और आशा करें कि कोई और इसका उपयोग नहीं कर रहा है? इसके अलावा, मेरे नारंगी_नोड के मामले में, क्या होगा अगर मैं red_node और yellow_node से विधियों का उपयोग करना चाहता हूं? क्या मुझे प्रति नोड कई प्रकार के स्टोर करने होंगे? यह जटिल लगता है।
निष्कर्ष
यह उदाहरण अत्यधिक जटिल या असामान्य नहीं लगता है (मैं अपने दिन के काम में कुछ इसी तरह काम कर रहा हूं, जहां नोड वास्तविक हार्डवेयर का प्रतिनिधित्व करते हैं जो सॉफ्टवेयर के माध्यम से नियंत्रित हो जाता है, और जो कि वे क्या हैं, उसके आधार पर बहुत अलग बात करते हैं)। फिर भी मुझे टेम्पलेट या अन्य तरीकों से ऐसा करने का एक साफ तरीका नहीं पता होगा। कृपया ध्यान दें कि मैं समस्या को समझने की कोशिश कर रहा हूं, न कि अपने उदाहरण का बचाव करने के लिए। मेरे जैसे पेजों के पढ़ने से एसओ उत्तर मैं ऊपर जुड़ा हुआ है और विकीबूक पर यह पृष्ठ लगता है कि मैं आरटीटीआई का दुरुपयोग कर रहा हूं, लेकिन मैं सीखना चाहूंगा कि क्यों।
इसलिए, मेरे मूल प्रश्न पर वापस जाएं: RTTI का उपयोग करने पर 'शुद्ध बहुरूपता' क्यों बेहतर है?
node_base
एक पुस्तकालय का हिस्सा है और उपयोगकर्ता अपने स्वयं के नोड प्रकार बनाएंगे। फिर वे एक और समाधान की अनुमति देने के लिए संशोधित नहीं कर सकतेnode_base
हैं, इसलिए हो सकता है कि RTTI फिर उनका सबसे अच्छा विकल्प बन जाए। दूसरी ओर, इस तरह के पुस्तकालय को डिजाइन करने के अन्य तरीके हैं ताकि नए नोड प्रकार आरटीटीआई (और नए नोड प्रकारों को भी डिजाइन करने के अन्य तरीके) का उपयोग किए बिना बहुत अधिक सुरुचिपूर्ण ढंग से फिट हो सकें।