फ़ंक्शन पैरामीटर का डिफ़ॉल्ट मान


130

1।

int Add (int a, int b = 3);
int Add (int a, int b)
{

}

2।

int Add (int a, int b);
int Add (int a, int b = 3)
{

}

दोनों कार्य; मानक तरीका कौन सा है और क्यों ?

जवाबों:


203

यदि आप एक हेडर फाइल में डिक्लेरेशन और एक अलग .cppफाइल में डेफिनिशन और एक अलग फाइल #includeसे हेडर डालते हैं .cpp, तो आप अंतर देख पाएंगे।

विशेष रूप से, मान लें:

lib.h

int Add(int a, int b);

lib.cpp

int Add(int a, int b = 3) {
   ...
}

test.cpp

#include "lib.h"

int main() {
    Add(4);
}

का संकलन है test.cpp डिफ़ॉल्ट पैरामीटर घोषणा को नहीं देखेगा, और एक त्रुटि के साथ विफल हो जाएगा।

इस कारण से, डिफ़ॉल्ट पैरामीटर परिभाषा आमतौर पर फ़ंक्शन घोषणा में निर्दिष्ट होती है :

lib.h

int Add(int a, int b = 3);

फिर bकई बार परिभाषित किया जाएगा, एक बार प्रत्येक संकलन इकाई के लिए जो इसमें शामिल है lib.h, क्या यह सही है?
httpinterpret

@httpinterpret: एक अर्थ में हां, प्रत्येक फ़ाइल के bलिए एक बार डिफ़ॉल्ट मान निर्धारित किया जाता .cppहै जिसमें हेडर शामिल होता है। लेकिन यह ठीक है, क्योंकि आपको केवल Addफ़ंक्शन की एक घोषणा मिली है।
ग्रेग हेविगेल

1
@httpinterpret कॉलर कोड जेनरेट होने पर कंपाइलर डिफ़ॉल्ट पैरामीटर द्वारा निर्दिष्ट पैरामीटर नहीं जोड़ेगा। यही कारण है कि डिफ़ॉल्ट मान फ़ंक्शन प्रोटोटाइप में होना चाहिए और फ़ंक्शन कार्यान्वयन में नहीं। पैरामीटर को चर परिभाषा के अर्थ में परिभाषित नहीं किया गया है क्योंकि प्रोटोटाइप चर को परिभाषित नहीं करता है।
हार्पर

1
इस उत्तर को संपादित किया जा सकता है क्योंकि एक त्वरित पार्सिंग (बस कोड को देख रहा है और "इस कारण से," तक नहीं जा रहा है) ने मुझे आपके विपरीत का मतलब समझा।
गेब्रियल डेविलर्स

44

C ++ में पैरामीटर सूची में उनके स्थान के संबंध में डिफ़ॉल्ट तर्कों पर लगाई गई आवश्यकताएँ निम्नानुसार हैं:

  1. किसी दिए गए पैरामीटर के लिए डिफ़ॉल्ट तर्क को एक से अधिक बार निर्दिष्ट नहीं किया जाना है। इसे एक से अधिक बार निर्दिष्ट करना (समान डिफ़ॉल्ट मान के साथ भी) अवैध है।

  2. डिफ़ॉल्ट तर्कों वाले पैरामीटर को पैरामीटर सूची के अंत में एक सन्निहित समूह बनाना होता है।

अब, इस बात को ध्यान में रखते हुए, C ++ में आपको उन मापदंडों के सेट को "बढ़ने" की अनुमति दी जाती है जिनमें फ़ंक्शन की एक घोषणा से दूसरे तक डिफ़ॉल्ट तर्क होते हैं, जब तक कि उपरोक्त आवश्यकताओं को लगातार संतुष्ट नहीं किया जाता है।

उदाहरण के लिए, आप कोई डिफ़ॉल्ट तर्क के साथ एक फ़ंक्शन की घोषणा कर सकते हैं

void foo(int a, int b);

इस तरह की घोषणा के बाद उस फ़ंक्शन को कॉल करने के लिए आपको दोनों तर्क स्पष्ट रूप से निर्दिष्ट करने होंगे।

एक ही अनुवाद इकाई में बाद में (आगे नीचे), आप इसे फिर से घोषित कर सकते हैं, लेकिन इस बार एक डिफ़ॉल्ट तर्क के साथ

void foo(int a, int b = 5);

और इस बिंदु पर आप इसे केवल एक स्पष्ट तर्क के साथ कह सकते हैं।

इसके अलावा, आप इसे फिर से घोषित कर सकते हैं फिर से एक और डिफ़ॉल्ट तर्क जोड़ सकते हैं

void foo(int a = 1, int b);

और इस बिंदु से आप इसे बिना किसी स्पष्ट तर्क के कह सकते हैं।

पूर्ण उदाहरण निम्नानुसार लग सकता है

void foo(int a, int b);

int main()
{
  foo(2, 3);

  void foo(int a, int b = 5); // redeclare
  foo(8); // OK, calls `foo(8, 5)`

  void foo(int a = 1, int b); // redeclare again
  foo(); // OK, calls `foo(1, 5)`
}

void foo(int a, int b)
{
  // ...
}

आपके प्रश्न में कोड के लिए, दोनों प्रकार पूरी तरह से मान्य हैं, लेकिन उनका मतलब अलग-अलग चीजों से है। पहला संस्करण दूसरे पैरामीटर के लिए तुरंत एक डिफ़ॉल्ट तर्क की घोषणा करता है। दूसरा वेरिएंट शुरू में आपके फ़ंक्शन को बिना किसी डिफ़ॉल्ट तर्क के घोषित करता है और फिर दूसरे पैरामीटर के लिए एक जोड़ता है।

आपकी दोनों घोषणाओं का शुद्ध प्रभाव (यानी जिस तरह से इसे कोड द्वारा देखा जाता है जो दूसरी घोषणा का अनुसरण करता है) बिल्कुल वैसा ही है: फ़ंक्शन में इसके दूसरे पैरामीटर के लिए डिफ़ॉल्ट तर्क है। हालांकि, यदि आप पहली और दूसरी घोषणाओं के बीच कुछ कोड को निचोड़ने का प्रबंधन करते हैं, तो ये दो संस्करण अलग-अलग व्यवहार करेंगे। दूसरे संस्करण में फ़ंक्शन में घोषणाओं के बीच कोई डिफ़ॉल्ट तर्क नहीं है, इसलिए आपको स्पष्ट रूप से दोनों तर्क निर्दिष्ट करने होंगे।


मुझे नहीं लगता कि आपका कोड परिभाषित शून्य foo (int a = 1, int b) काम करेगा। एक वैकल्पिक पैरामीटर के बाद आपके पास सभी वैकल्पिक पैरामीटर होने चाहिए। यह एक सिंटैक्स त्रुटि है (कम से कम मेरे सिस्टम पर जी ++ 4.5.3 के साथ)।
नीलेश

@ निलेश: जैसा कि मैंने स्पष्ट रूप से कहा है (और जो इस उदाहरण का पूरा बिंदु है) void foo(int a = 1, int b)काम करने के लिए इसे बाद में घोषित करना होगा void foo(int a, int b = 5)। हाँ, यह काम करेगा। और नहीं, यह एक वाक्यविन्यास त्रुटि नहीं है। g ++ 4.5.3 इसे पूरी तरह से ठीक करेगा।
चींटी

ठीक है, इसलिए फ़ंक्शन पिछले घोषणा से बी का मूल्य लेता है। अब बात हो रही है। धन्यवाद :-)
नीलेश

1
@ निलेश: हाँ, डिफ़ॉल्ट तर्क घोषणाएँ अनुवाद इकाई में पिछले सभी घोषणाओं में जमा होती हैं।
ए.टी.

1
मुझे अपने फ़ंक्शन प्रोटोटाइप को चर नामों के बिना लिखना पसंद है, जैसे int foo(int)। मुझे लगता है कि मैं int foo(int=5)फिर से लिख सकता हूं , पैरामीटर नामों को छोड़कर। ऐसा लगता है कि अभी तक किसी ने उल्लेख नहीं किया है।
विक्टर आइजखौट

5

पहला तरीका दूसरे को पसंद किया जाएगा।

ऐसा इसलिए है क्योंकि हेडर फ़ाइल दिखाएगा कि पैरामीटर वैकल्पिक है और इसका डिफ़ॉल्ट मान क्या होगा। इसके अतिरिक्त, यह सुनिश्चित करेगा कि डिफ़ॉल्ट मान समान होगा, कोई भी संबंधित .cpp फ़ाइल के कार्यान्वयन के लिए नहीं।

दूसरे तरीके में, दूसरे पैरामीटर के लिए डिफ़ॉल्ट मान की कोई गारंटी नहीं है। डिफ़ॉल्ट मान बदल सकता है, इसी .cpp फ़ाइल को लागू करने के आधार पर।


4

डिफ़ॉल्ट तर्क को फ़ंक्शन नाम की पहली घटना के साथ निर्दिष्ट किया जाना चाहिए - आमतौर पर, फ़ंक्शन प्रोटोटाइप में। यदि फ़ंक्शन प्रोटोटाइप को छोड़ दिया गया है क्योंकि फ़ंक्शन परिभाषा भी प्रोटोटाइप के रूप में कार्य करती है, तो फ़ंक्शन हेडर में डिफ़ॉल्ट तर्क निर्दिष्ट किए जाने चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.