आप उन हिस्सों को अलग करने के लिए टेम्पलेट विशेषज्ञता का उपयोग कर सकते हैं जिनके पास केवल गैर-कॉन्स्ट ऑब्जेक्ट पर उद्देश्य है।
खिलौना वर्ग के लिए एक कार्यान्वयन निम्नलिखित है। इसमें 10 इंच के साथ एक एकल सी-सरणी सदस्य बनाम है, और, हमारे उद्देश्यों के लिए, यह केवल तभी मान्य होता है जब उनमें से प्रत्येक शून्य के बराबर होता है।
class ten_zeroes {
int v[10];
void fix(int pos) {v[pos] = 0;}
public:
ten_zeroes() { // construct as invalid object
for (int i=0;i<10;i++) {
v[i] = i;
}
}
};
देखें कि मैं पहले से ही एक समारोह सदस्य है कि गलत स्थिति ठीक करता है, और एक अच्छा निर्माता है कि यह गलत वस्तु के रूप में आरंभ किए गए (ऐसा नहीं है: डी)
हम करने जा रहे हैं के बाद से टेम्पलेट का उपयोग करें, हमें कक्षा के बाहर चेक/फिक्स चक्र के कार्यान्वयन को स्थानांतरित करने की आवश्यकता है। प्रासंगिक कार्यों के लिए v
और fix()
विधि तक पहुंचने में सक्षम होने के लिए, हम उन्हें मित्र बना देंगे। यहाँ
// Check and maybe fix object
template<typename T>
bool check(T& obj){
bool result = true;
for(int i=0;i<10;i++) {
if (obj.v[i]) {
result = false;
fix(obj, i);
}
}
return result;
}
अब मुश्किल हिस्सा है: हमारे कोड अब लगता है कि:
class ten_zeroes {
int v[10];
void fix(int pos) {v[pos] = 0;}
public:
ten_zeroes() { // construct as invalid object
for (int i=0;i<10;i++) {
v[i] = i;
}
}
template<typename T>
friend void fix(T& obj, int pos);
template<typename T>
friend bool check(T& obj);
};
check()
के कार्यान्वयन सरल है। हम दृढ़ता के आधार पर व्यवहार बदलने के लिए हमारे fix()
फ़ंक्शन चाहते हैं। इसके लिए हमें टेम्पलेट का विशेषज्ञ होना होगा। एक गैर-कॉन्स ऑब्जेक्ट के लिए, यह स्थिति को ठीक करेगा। एक स्थिरांक एक के लिए, यह कुछ भी नहीं होगा:
// For a regular object, fix the position
template<typename T>
void fix(T& obj, int pos) { obj.fix(pos);}
// For a const object, do nothing
template<typename T>
void fix(const T& obj, int pos) {}
अंत में, हम हमारे is_valid()
और make_valid()
तरीकों लिखते हैं, और यहाँ हम पूर्ण कार्यान्वयन है:
#include <iostream>
class ten_zeroes {
int v[10];
void fix(int pos) {v[pos] = 0;}
public:
ten_zeroes() { // construct as invalid object
for (int i=0;i<10;i++) {
v[i] = i;
}
}
bool is_valid() const {return check(*this);} // since this is const, it will run check with a const ten_zeroes object
void make_valid() { check(*this);} // since this is non-const , it run check with a non-const ten_zeroes object
template<typename T>
friend void fix(T& obj, int pos);
template<typename T>
friend bool check(T& obj);
};
// For a regular object, fix the position
template<typename T>
void fix(T& obj, int pos) { obj.fix(pos);}
// For a const object, do nothing
template<typename T>
void fix(const T& obj, int pos) {}
// Check and maybe fix object
template<typename T>
bool check(T& obj){
bool result = true;
for(int i=0;i<10;i++) {
if (obj.v[i]) {
result = false;
fix(obj, i);
}
}
return result;
}
int main(){
ten_zeroes a;
std::cout << a.is_valid() << a.is_valid(); // twice to make sure the first one didn't make any changes
a.make_valid(); // fix the object
std::cout << a.is_valid() << std::endl; // check again
}
मुझे आशा है कि आप कोई आपत्ति नहीं है main()
वहां कार्य करें। यह हमारे छोटे खिलौने का परीक्षण करेगा, और उम्मीद के अनुसार 001
आउटपुट करेगा। अब इस कोड पर किसी भी रखरखाव को कोड डुप्लिकेशंस से निपटना नहीं होगा, जो आप शायद टालने का इरादा रखते थे। मुझे आशा है कि यह मददगार था।
बेशक, यदि आप अंतिम उपयोगकर्ता से इन कार्यान्वयन विवरणों को छिपाने का इरादा रखते हैं, तो आपको उन्हें उचित विवरण नाम स्थान पर ले जाना चाहिए। मैं इसे आप तक छोड़ दूंगा :)
स्प्लिट चेक और "फिक्सिंग" दो अलग-अलग कार्यों में? चेक 'const' है और ठीक नहीं है? – crashmstr
मैं @crashmstr से सहमत हूं, जिसमें एक कार्य है जो दो अलग-अलग चीजें करता है, एक खराब डिजाइन गंध है। –
असल में, पहले से ही 'चेक वैलिडिटी' नाम से पता चलता है कि यह फ़ंक्शन केवल एक चेक करता है और यह हो सकता है। यदि आप चाहते हैं करने के लिए 'MakeValid' यह कुछ अलग है (और यह स्थिरांक नहीं होना चाहिए ...) – user463035818