अतिरिक्त अतिरंजित कास्ट एपीआई स्टैंड-पॉइंट से खराब हैं:
कॉलर या एपीआई उपयोगकर्ता (यह केवल कार्यान्वयन को बाधित करता है) के लिए कोई सार्थक वादा नहीं करते हुए आपके एपीआई के मूल्य सुराग से पारित आंतरिक प्रकार के मापदंडों के लिए अपने कोड में अतिरिक्त अतिरंजित कास्ट डाल रहा है ।
जब जरूरत नहीं हो तो एक एपीआई में बहुत से 'कास्ट' " रोते हुए भेड़िये " की तरह होते हैं, अंततः लोग 'कॉन्स्ट' को नजरअंदाज करना शुरू कर देंगे क्योंकि यह सभी जगह है और इसका मतलब है कि ज्यादातर समय कुछ भी नहीं है।
एपीआई में अतिरिक्त कास्ट्स के लिए "रिडक्टियो एड एब्सर्डम" तर्क इन पहले दो बिंदुओं के लिए अच्छा है यदि अधिक कॉन्स्ट पैरामीटर अच्छे हैं, तो हर तर्क जिसमें इस पर एक कॉस्ट हो सकती है, SHOULD का एक कॉस्ट है। वास्तव में, यदि यह सही मायने में अच्छा था, तो आप चाहते हैं कि आप मापदंडों के लिए डिफ़ॉल्ट हों और आपके पास "परिवर्तनशील" जैसे कीवर्ड हों, जब आप पैरामीटर बदलना चाहते हैं।
तो जहाँ भी हम कर सकते हैं वहाँ कास्ट में डालने की कोशिश करते हैं:
void mungerum(char * buffer, const char * mask, int count);
void mungerum(char * const buffer, const char * const mask, const int count);
ऊपर दिए गए कोड की लाइन पर विचार करें। न केवल घोषणा अधिक अव्यवस्थित और लंबी और पढ़ने में कठिन है, बल्कि चार में से तीन 'कास्ट' कीवर्ड को एपीआई उपयोगकर्ता द्वारा सुरक्षित रूप से अनदेखा किया जा सकता है। हालाँकि, 'कॉन्स्ट' के अतिरिक्त उपयोग ने दूसरी लाइन को संभावित रूप से खतरनाक बना दिया है !
क्यों?
पहले पैरामीटर का एक त्वरित गलत char * const buffer
अर्थ आपको यह सोच सकता है कि यह डेटा बफर में मेमोरी को संशोधित नहीं करेगा जो कि - में पारित हो गया है, लेकिन यह सच नहीं है! सुपरफ्लस 'कास्ट' स्कैन या गलत तरीके से तेज़ी से फैलने पर आपके एपीआई के बारे में खतरनाक और गलत धारणाएं पैदा कर सकता है ।
एक कोड कार्यान्वयन स्टैंड-पॉइंट के साथ-साथ सुपरफ़्लुअस कॉस्ट खराब हैं:
#if FLEXIBLE_IMPLEMENTATION
#define SUPERFLUOUS_CONST
#else
#define SUPERFLUOUS_CONST const
#endif
void bytecopy(char * SUPERFLUOUS_CONST dest,
const char *source, SUPERFLUOUS_CONST int count);
यदि FLEXIBLE_IMPLEMENTATION सही नहीं है, तो API "होनहार" है जो फ़ंक्शन को नीचे दिए गए तरीके से लागू नहीं करता है।
void bytecopy(char * SUPERFLUOUS_CONST dest,
const char *source, SUPERFLUOUS_CONST int count)
{
// Will break if !FLEXIBLE_IMPLEMENTATION
while(count--)
{
*dest++=*source++;
}
}
void bytecopy(char * SUPERFLUOUS_CONST dest,
const char *source, SUPERFLUOUS_CONST int count)
{
for(int i=0;i<count;i++)
{
dest[i]=source[i];
}
}
यह एक बहुत ही मूर्खतापूर्ण वादा है। आपको ऐसा वादा क्यों करना चाहिए जो आपके कॉल करने वाले को कोई लाभ नहीं देता है और केवल आपके कार्यान्वयन को सीमित करता है?
ये दोनों एक ही फ़ंक्शन के पूरी तरह से मान्य कार्यान्वयन हैं हालांकि आपने जो कुछ भी किया है वह आपकी पीठ के पीछे अनावश्यक रूप से एक हाथ से बंधा हुआ है।
इसके अलावा, यह एक बहुत उथला वादा है जो आसानी से (और कानूनी रूप से दरकिनार) है।
inline void bytecopyWrapped(char * dest,
const char *source, int count)
{
while(count--)
{
*dest++=*source++;
}
}
void bytecopy(char * SUPERFLUOUS_CONST dest,
const char *source,SUPERFLUOUS_CONST int count)
{
bytecopyWrapped(dest, source, count);
}
देखिए, मैंने इसे वैसे भी लागू किया, भले ही मैंने वादा किया था कि - सिर्फ एक आवरण समारोह का उपयोग करके। यह तब होता है जब बुरा आदमी किसी फिल्म में किसी को नहीं मारने का वादा करता है और अपने गुर्गे को इसके बजाय उन्हें मारने का आदेश देता है।
उन अतिरंजित कास्ट एक फिल्म बुरे आदमी से एक वादा से अधिक के लायक नहीं हैं।
लेकिन झूठ बोलने की क्षमता और भी बदतर हो जाती है:
मुझे ज्ञान दिया गया है कि आप शीर्ष लेख (घोषणा) और कोड (परिभाषा) का उपयोग कर सकते हैं। कास्ट-हैप्पी अधिवक्ताओं का दावा है कि यह एक अच्छी बात है क्योंकि यह आपको केवल परिभाषा में कास्ट करने देता है।
// Example of const only in definition, not declaration
class foo { void test(int *pi); };
void foo::test(int * const pi) { }
हालाँकि, यह वाक्य सही है ... आप केवल घोषणा में एक स्पस्ट कॉन्स्ट डाल सकते हैं और परिभाषा में इसे अनदेखा कर सकते हैं। यह केवल एपीआई में एक भयानक बात और एक भयानक झूठ में अतिशयोक्तिपूर्ण कास्ट बनाता है - इस उदाहरण को देखें:
class foo
{
void test(int * const pi);
};
void foo::test(int *pi) // Look, the const in the definition is so superfluous I can ignore it here
{
pi++; // I promised in my definition I wouldn't modify this
}
जब वह परिवर्तनशील परिवर्तन करना चाहता है या गैर-कॉस्ट रेफरेंस द्वारा वेरिएबल को पास करना चाहता है, तो वास्तव में सभी सुपरफ्लुअस कॉन्स्ट उसे एक अन्य स्थानीय कॉपी या एक रैपर फ़ंक्शन का उपयोग करने के लिए मजबूर करके कार्यान्वयनकर्ता के कोड को कम पठनीय बनाता है।
इस उदाहरण को देखें। कौन सा अधिक पठनीय है? क्या यह स्पष्ट है कि दूसरे फ़ंक्शन में अतिरिक्त चर का एकमात्र कारण यह है कि कुछ एपीआई डिजाइनर ने एक शानदार अंतर में फेंक दिया?
struct llist
{
llist * next;
};
void walkllist(llist *plist)
{
llist *pnext;
while(plist)
{
pnext=plist->next;
walk(plist);
plist=pnext; // This line wouldn't compile if plist was const
}
}
void walkllist(llist * SUPERFLUOUS_CONST plist)
{
llist * pnotconst=plist;
llist *pnext;
while(pnotconst)
{
pnext=pnotconst->next;
walk(pnotconst);
pnotconst=pnext;
}
}
उम्मीद है कि हमने यहां कुछ सीखा है। सुपरफ्लस कांस्टेबल एक एपीआई-अव्यवस्थित आंखें, एक कष्टप्रद नाग, एक उथला और अर्थहीन वादा, एक अनावश्यक बाधा है, और कभी-कभी बहुत खतरनाक गलतियों की ओर जाता है।