ফাংশন প্যারামিটারের ডিফল্ট মান


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, তা কি ঠিক?
HTTP ব্যাখ্যা করুন

@httpinter ব্যাখ্যা: এক অর্থে হ্যাঁ, শিরোনাম অন্তর্ভুক্ত প্রতিটি ফাইলের bজন্য ডিফল্ট মান একবারে সংজ্ঞায়িত করা হয় । তবে এটি ঠিক আছে, কারণ আপনি কেবলমাত্র ফাংশনটির একটি ঘোষণা পেয়েছেন । .cppAdd
গ্রেগ হিউগিল

1
@httpinter ব্যাখ্যা সংকলক কলার কোডটি উত্সাহিত করার পরে ডিফল্ট প্যারামিটার দ্বারা নির্দিষ্ট না হওয়া প্যারামিটার যুক্ত করবে will এজন্য ডিফল্ট মানটি ফাংশন প্রোটোটাইপে থাকতে হবে এবং ফাংশন বাস্তবায়নে নয়। প্রোটোটাইপ ভেরিয়েবল সংজ্ঞায়িত না হওয়ায় প্যারামিটারটি পরিবর্তনশীল সংজ্ঞা অর্থে সংজ্ঞায়িত হয় না।
হার্পার

1
এই উত্তরটি সম্পাদনা করা যেতে পারে কারণ দ্রুত পার্সিং (কেবল কোডটির দিকে তাকানো এবং "এই কারণে," না যাওয়া পর্যন্ত) আমাকে আপনার বক্তব্যটির বিপরীতে বুঝতে পেরেছিল।
গ্যাব্রিয়েল ডেভিলার্স

44

সি ++ এ প্যারামিটার তালিকায় তাদের অবস্থান সম্পর্কিত ডিফল্ট আর্গুমেন্টগুলির উপর আরোপিত প্রয়োজনীয়তা নিম্নরূপ:

  1. প্রদত্ত প্যারামিটারের জন্য ডিফল্ট যুক্তিটি একবারের বেশি নির্দিষ্ট করতে হবে না। এটি একাধিকবার নির্দিষ্ট করা (এমনকি একই ডিফল্ট মান সহ) অবৈধ।

  2. ডিফল্ট যুক্তিযুক্ত প্যারামিটারগুলিকে প্যারামিটার তালিকার শেষে একটি সুসংগত গ্রুপ গঠন করতে হবে।

এখন, এই বিষয়টি মাথায় রেখে, সি ++ এ আপনাকে ফাংশনটির একটি ঘোষণা থেকে পরের দিকে ডিফল্ট আর্গুমেন্ট রয়েছে এমন পরামিতিগুলির সেটকে "বৃদ্ধি" করার অনুমতি দেওয়া হচ্ছে, যতক্ষণ না উপরের প্রয়োজনীয়তা অবিচ্ছিন্নভাবে তত্ক্ষণিত হয়।

উদাহরণস্বরূপ, আপনি কোনও ডিফল্ট তর্ক ছাড়াই একটি ফাংশন ঘোষণা করতে পারেন

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) কাজ করবে। একটি alচ্ছিক প্যারামিটারের পরে আপনার সমস্ত optionচ্ছিক পরামিতি থাকতে হবে। এটি একটি বাক্য গঠন ত্রুটি (কমপক্ষে আমার সিস্টেমে g ++ 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

প্রথম উপায় দ্বিতীয় পছন্দ করা হবে।

এর কারণ হ্যাডার ফাইলটি দেখায় যে প্যারামিটারটি alচ্ছিক এবং এর ডিফল্ট মানটি কী হবে। তদ্ব্যতীত, এটি নিশ্চিত করবে যে ডিফল্ট মানটি একই হবে, সংশ্লিষ্ট .cpp ফাইলটির প্রয়োগ কোনও বিষয় নয়।

দ্বিতীয় উপায়ে, দ্বিতীয় প্যারামিটারের জন্য কোনও ডিফল্ট মানের কোনও গ্যারান্টি নেই। ডিফল্ট মান পরিবর্তন করতে পারে, কীভাবে সম্পর্কিত .cpp ফাইল বাস্তবায়িত হয় তার উপর নির্ভর করে।


4

ডিফল্ট আর্গুমেন্টগুলি ফাংশন নামের প্রথম ঘটনার সাথে অবশ্যই নির্দিষ্ট করা উচিত — সাধারণত, ফাংশন প্রোটোটাইপে। যদি ফাংশন প্রোটোটাইপ বাদ দেওয়া হয় কারণ ফাংশন সংজ্ঞাটি প্রোটোটাইপ হিসাবেও কাজ করে, তবে ফাংশন শিরোনামে ডিফল্ট আর্গুমেন্টগুলি নির্দিষ্ট করা উচিত।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.