C++
कार्य अतिभार
खोज…
परिचय
ओवरलोड रिज़ॉल्यूशन पर अलग विषय भी देखें
टिप्पणियों
अस्पष्टता तब हो सकती है जब किसी प्रकार को एक से अधिक प्रकारों में परिवर्तित किया जा सकता है और उस विशिष्ट प्रकार के लिए कोई मिलान कार्य नहीं होता है।
उदाहरण के लिए:
void foo(double, double);
void foo(long, long);
//Call foo with 2 ints
foo(1, 2); //Function call is ambiguous - int can be converted into a double/long at the same time
फंक्शन ओवरलोडिंग क्या है?
फंक्शन ओवरलोडिंग के एक ही दायरे में एक ही दायरे में घोषित किए गए कई कार्य एक ही स्थान पर मौजूद होते हैं (जिन्हें स्कोप के रूप में जाना जाता है ) केवल उनके हस्ताक्षर में भिन्न होते हैं, जिसका अर्थ है कि वे जो तर्क स्वीकार करते हैं।
मान लीजिए कि आप सामान्यीकृत मुद्रण क्षमताओं के लिए कार्यों की एक श्रृंखला लिख रहे हैं, जो std::string
शुरू होती है:
void print(const std::string &str)
{
std::cout << "This is a string: " << str << std::endl;
}
यह ठीक काम करता है, लेकिन मान लीजिए कि आप एक ऐसा फंक्शन चाहते हैं जो एक int
भी स्वीकार करे और प्रिंट भी। आप लिख सकते हैं:
void print_int(int num)
{
std::cout << "This is an int: " << num << std::endl;
}
लेकिन क्योंकि दो कार्य विभिन्न मापदंडों को स्वीकार करते हैं, आप बस लिख सकते हैं:
void print(int num)
{
std::cout << "This is an int: " << num << std::endl;
}
अब आपके पास 2 कार्य हैं, दोनों का नाम print
, लेकिन विभिन्न हस्ताक्षर के साथ। एक std::string
स्वीकार करता है, दूसरा एक int
। अब आप विभिन्न नामों के बारे में चिंता किए बिना उन्हें कॉल कर सकते हैं:
print("Hello world!"); //prints "This is a string: Hello world!"
print(1337); //prints "This is an int: 1337"
के बजाय:
print("Hello world!");
print_int(1337);
जब आपके पास ओवरलोड फ़ंक्शन होते हैं, तो कंपाइलर आपके द्वारा प्रदान किए जाने वाले मापदंडों से कॉल करने के लिए कौन से फ़ंक्शन को प्रभावित करता है। फंक्शन ओवरलोड लिखते समय सावधानी बरतनी चाहिए। उदाहरण के लिए, निहितार्थ रूपांतरणों के साथ:
void print(int num)
{
std::cout << "This is an int: " << num << std::endl;
}
void print(double num)
{
std::cout << "This is a double: " << num << std::endl;
}
अब यह तुरंत स्पष्ट नहीं है कि जब आप लिखते हैं तो print
का अधिभार किसे कहा जाता है:
print(5);
और आपको अपने संकलक को कुछ सुराग देने की आवश्यकता हो सकती है, जैसे:
print(static_cast<double>(5));
print(static_cast<int>(5));
print(5.0);
वैकल्पिक मापदंडों को स्वीकार करने वाले अधिभार को लिखते समय कुछ देखभाल की भी आवश्यकता होती है:
// WRONG CODE
void print(int num1, int num2 = 0) //num2 defaults to 0 if not included
{
std::cout << "These are ints: << num1 << " and " << num2 << std::endl;
}
void print(int num)
{
std::cout << "This is an int: " << num << std::endl;
}
क्योंकि कंपाइलर के पास यह बताने का कोई तरीका नहीं है कि वैकल्पिक दूसरे पैरामीटर के कारण print(17)
या print(17)
फ़ंक्शन जैसे कॉल का मतलब पहले या दूसरे फ़ंक्शन के लिए है या नहीं, यह संकलन करने में विफल होगा।
फ़ंक्शन ओवरलोडिंग में वापसी प्रकार
ध्यान दें कि आप किसी फ़ंक्शन को उसके रिटर्न प्रकार के आधार पर अधिभार नहीं दे सकते। उदाहरण के लिए:
// WRONG CODE
std::string getValue()
{
return "hello";
}
int getValue()
{
return 0;
}
int x = getValue();
यह एक संकलन त्रुटि का कारण होगा क्योंकि कंपाइलर getValue
किस संस्करण को कॉल करने में सक्षम नहीं होगा, भले ही रिटर्न प्रकार एक int
को सौंपा गया हो।
सदस्य समारोह cv- क्वालीफायर ओवरलोडिंग
जब वे उस वर्ग के लिए cv- योग्य संदर्भ के माध्यम से पहुँचते हैं, तो एक वर्ग के भीतर कार्य अतिभारित हो सकते हैं; इस सबसे अधिक के लिए अधिभार लिए किया जाता है const
है, लेकिन के लिए अधिभार के लिए इस्तेमाल किया जा सकता है volatile
और const volatile
भी। इसका कारण यह है सभी गैर स्थिर सदस्य कार्यों ले this
एक छिपा पैरामीटर, जो सीवी-क्वालिफायर के लिए लागू कर रहे हैं। यह आमतौर पर के लिए अधिभार लिए किया जाता है const
, लेकिन यह भी के लिए इस्तेमाल किया जा सकता volatile
और const volatile
।
यह आवश्यक है क्योंकि एक सदस्य फ़ंक्शन को केवल तभी कॉल किया जा सकता है जब वह कम से कम cv-योग्य हो जैसा कि उस पर कॉल किया गया है। हालांकि एक नॉन- const
इंस्टेंस const
और नॉन- const
मेंबर्स दोनों को कॉल कर सकता है, एक const
इंस्टेंस केवल const
मेंबर्स को कॉल कर सकता है। यह एक फ़ंक्शन को कॉलिंग इंस्टेंस के cv-क्वालिफायर के आधार पर अलग व्यवहार करने की अनुमति देता है, और प्रोग्रामर को उस क्वालिफायर (एस) के साथ एक संस्करण प्रदान नहीं करके एक अवांछित cv-क्वालिफायर (एस) के लिए कार्यों को अस्वीकार करने की अनुमति देता है।
कुछ बुनियादी के साथ एक वर्ग print
विधि जा सकता है const
तो जैसे अतिभारित:
#include <iostream>
class Integer
{
public:
Integer(int i_): i{i_}{}
void print()
{
std::cout << "int: " << i << std::endl;
}
void print() const
{
std::cout << "const int: " << i << std::endl;
}
protected:
int i;
};
int main()
{
Integer i{5};
const Integer &ic = i;
i.print(); // prints "int: 5"
ic.print(); // prints "const int: 5"
}
यह const
शुद्धता का एक प्रमुख सिद्धांत है: सदस्य कार्यों को const
रूप में चिह्नित करके, उन्हें const
इंस्टेंस पर कॉल करने की अनुमति दी जाती है, जो बदले में फ़ंक्शंस को const
पॉइंटर्स / रेफ़रेंस के रूप में लेने की अनुमति देता है, यदि उन्हें संशोधित करने की आवश्यकता नहीं है। यह कोड को यह निर्दिष्ट करने की अनुमति देता है कि क्या यह cv-क्वालिफायर के बिना const
और संशोधित मापदंडों के रूप में असमान मानकों को ले कर राज्य को संशोधित करता है, जिससे कोड सुरक्षित और अधिक पठनीय हो सकता है।
class ConstCorrect
{
public:
void good_func() const
{
std::cout << "I care not whether the instance is const." << std::endl;
}
void bad_func()
{
std::cout << "I can only be called on non-const, non-volatile instances." << std::endl;
}
};
void i_change_no_state(const ConstCorrect& cc)
{
std::cout << "I can take either a const or a non-const ConstCorrect." << std::endl;
cc.good_func(); // Good. Can be called from const or non-const instance.
cc.bad_func(); // Error. Can only be called from non-const instance.
}
void const_incorrect_func(ConstCorrect& cc)
{
cc.good_func(); // Good. Can be called from const or non-const instance.
cc.bad_func(); // Good. Can only be called from non-const instance.
}
इस का एक आम उपयोग के रूप में accessors घोषित है const
गैर के रूप में, और mutators const
।
किसी भी वर्ग के सदस्यों को एक const
सदस्य फ़ंक्शन के भीतर संशोधित नहीं किया जा सकता है। अगर वहाँ कुछ सदस्य है कि तुम सच में इस तरह के एक लॉक करना, संशोधित करने की आवश्यकता है std::mutex
, आप इसे के रूप में घोषणा कर सकते हैं mutable
:
class Integer
{
public:
Integer(int i_): i{i_}{}
int get() const
{
std::lock_guard<std::mutex> lock{mut};
return i;
}
void set(int i_)
{
std::lock_guard<std::mutex> lock{mut};
i = i_;
}
protected:
int i;
mutable std::mutex mut;
};