ফাংশন (Functions)
শুধুই "কল (Call) এবং রিটার্ন (Return)"-এর চেয়েও অনেক বেশি কিছু
বেশিরভাগ ভাষাতেই (languages), কোনো ফাংশনের নাম (function name) মূলত ইউনিক বা অদ্বিতীয় (unique) হয়ে থাকে — অর্থাৎ একটি নাম (one name), একটি কাজ বা আচরণ (one behavior)। কিন্তু সি++ (C++) মূলত এই নিয়মটিকে বেশ শক্তিশালী একটি উপায়ে ভেঙেছে। এক্ষেত্রে আপনার একই নামের একাধিক ফাংশন (multiple functions with the same name) থাকতে পারে, যেগুলো মূলত আপনি সেগুলোতে কী পাস (pass) করছেন তার ওপর ভিত্তি করে ভিন্ন ভিন্ন কাজ (different things) করতে পারে। একে মূলত ফাংশন ওভারলোডিং (function overloading) বলা হয়, আর এটিই হলো এখানকার অন্যতম একটি বৈশিষ্ট্য যা মূলত সি++-কে (C++) এতটা এক্সপ্রেসিব বা উন্নত ও সমৃদ্ধ (expressive) করে তোলে।
তবে এটি তো কেবল শুরু। সি++ (C++) মূলত আপনাকে এর যেকোনো ডিফল্ট আর্গুমেন্টের মানগুলোকেও (default argument values) সেট করার সুযোগ দেয়, এর ডেটাগুলোকে কপি (copy) বা রেফারেন্স (reference) করতে দেয়, এবং এমনকি কাজের মাঝখানেই (on the fly) কিছু ছোট ও নামহীন ফাংশনও (anonymous functions) তৈরি করার সুযোগ করে দেয়। চলুন, এদের প্রত্যেকটি টুল (tools) নিয়ে বিস্তারিত আলোচনা করা যাক।
ফাংশন ওভারলোডিং (Function Overloading) — একই নাম, তবে ব্লেড আলাদা (Same Name, Different Blades)
একটি print() ফাংশনের কথা চিন্তা করুন। ধরুন কখনো আপনি একটি ইনটিজারকে (integer) প্রিন্ট (print) করতে চান। আবার কখনো একটি স্ট্রিংকে (string)। কিংবা কখনো একটি ভেক্টরকে (vector)। এক্ষেত্রে সি-তে (C) ওই কাজগুলো করার জন্য আপনার আলাদা আলাদা করে printInt(), printStr(), printVec() নামের ফাংশনের প্রয়োজন হতো। কিন্তু সি++ (C++)-এ, এগুলো মূলত সবই শুধু print() নামেই কল বা ডাকা (called) হতে পারে — কারণ এখানকার কম্পাইলারটি (compiler) মূলত আপনার দেওয়া ওই আর্গুমেন্টগুলোর সংখ্যা এবং ধরন বা টাইপের (number and types of arguments) ওপর ভিত্তি করেই বুঝে ফেলে (figures out) যে এখানে ঠিক কোনটিকে কল (call) করতে হবে।
কার্যকর বা অ্যাকশনে থাকা ফাংশন ওভারলোডিং (Function Overloading in Action)
ডিফল্ট আর্গুমেন্ট (Default Arguments) — নব বা নবগুলোকে আগে থেকেই সেট করা (Pre-Set the Knobs)
কখনো কখনো কোনো একটি ফাংশনের একাধিক প্যারামিটার (parameters) থাকতে পারে, যেগুলো বেশিরভাগ সময়ই (usually) একই মান (same value) নিয়ে কাজ করে থাকে। এক্ষেত্রে যিনি কল (callers) করছেন তাকে দিয়ে প্রতিবার সেগুলো টাইপ করানোর বদলে, আপনি চাইলে সেখানকার প্যারামিটারগুলোর জন্য কিছু ডিফল্ট ভ্যালু (default values) দিয়ে দিতে পারেন। তবে এই ডিফল্টগুলোর ব্যবহার অবশ্যই ডানদিকের একেবারে শেষের (rightmost) প্যারামিটারটি থেকে শুরু করে তারপর বাম দিকে (left) যেতে হতে হবে — অর্থাৎ আপনি মাঝখান থেকে (in the middle) কোনো প্যারামিটারকে স্কিপ বা এড়িয়ে (skip) যেতে পারবেন না।
ডিফল্ট আর্গুমেন্ট (Default Arguments)
পাস বাই ভ্যালু (Pass by Value) বনাম পাস বাই রেফারেন্স (Pass by Reference)
এটি মূলত এমন একটি জায়গা যেখানে সি++ (C++) আপনাকে এমন কিছু নিয়ন্ত্রণ (control) দিয়ে থাকে, যা অন্যান্য প্রোগ্রামিং ভাষাগুলো (languages) বেশিরভাগ সময়ই লুকিয়ে (hide) রাখে। আপনি যখন কোনো একটি ফাংশনে কোনো আর্গুমেন্ট (argument) পাস করেন, তখন আপনি মূলত নির্ধারণ (choose) করতে পারেন যে:
- ভ্যালুর সাহায্যে বা বাই ভ্যালু (By value) — এখানকার ফাংশনটি (function) মূলত মূল কাজটির একটি কপি (copy) রিসিভ করে বা পায়। এক্ষেত্রে এর ভেতরের কোনো পরিবর্তন (Changes inside) কখনোই মূল ডেটাটির (original) ওপর কোনো প্রভাব (affect) ফেলে না।
- রেফারেন্সের সাহায্যে বা বাই রেফারেন্স (By reference - &) — এখানকার ফাংশনটি (function) মূলত এই আসল বা মূল (original) ডেটাটিকে পেয়ে থাকে। এক্ষেত্রে এর ভেতরের সমস্ত পরিবর্তনগুলো ওই কলারটির (caller's) ডেটাকে মডিফাই বা পরিবর্তন (modify) করে দেয়।
- কনস্ট্যান্ট রেফারেন্সের সাহায্যে বা বাই কনস্ট রেফারেন্স (By const reference - const &) — এখানকার ফাংশনটি (function) মূলত এর আসল (original) ডেটাটিকে পেলেও সেটি কখনোই পরিবর্তন না করার প্রতিশ্রুতি (promises not to modify it) দেয়। রিড-ওনলি অ্যাক্সেসের (read-only access) ক্ষেত্রে এটি মূলত সবচেয়ে ভালো (Best of both worlds) উপায়।
এটিকে আপনি মূলত একটি বই ধার দেওয়ার (lending a book) মতো করে চিন্তা করতে পারেন। বাই ভ্যালুর (By value) মানে হলো আপনি বইটিকে ফটোকপি (photocopy) করে শুধু ওই কপিটিকেই (copy) দিচ্ছেন। বাই রেফারেন্স (By reference) মানে হলো আপনি মূলত সেই আসল বইটিকেই (actual book) হস্তান্তর করছেন। আর বাই কনস্ট রেফারেন্স (By const reference) মানে হলো আপনি বইটি হস্তান্তর করার সময় ওই লোকটিকে বলছেন যে "এটি কেবলই পড়ার জন্য, এতে কোনো কিছু লেখা (write) যাবে না।"
পাস বাই রেফারেন্স (Pass by Reference) — দ্য ক্লাসিক সোয়াপ (The Classic Swap)
const Reference বা কনস্ট রেফারেন্স — বড় অবজেক্টের (Large Objects) জন্য দ্রুত (Fast) এবং নিরাপদ (Safe)
const রেফারেন্সের (যথা const std::string&, const std::vector<int>&) মাধ্যমেই পাস (Pass) করান — কারণ বাই ভ্যালুর (by value) মাধ্যমে পাস করালে এটি মূলত ওই সম্পূর্ণ অবজেক্টটিরই (entire object) একটি অনুলিপি বা কপি তৈরি করবে! তাই বাই ভ্যালুর (by value) এই ব্যবহারটিকে শুধু খুব ছোট, বা সহজেই কপি করা যায় এমন টাইপগুলো (cheap-to-copy types) যেমন int, char, bool, এবং double-এর ব্যাপারেই সীমিত রাখুন।ইনলাইন ফাংশনগুলো (Inline Functions) এবং auto রিটার্ন টাইপ (Return Type)
inline হলো কম্পাইলারের (compiler) জন্য এক ধরনের সংকেত বা হিন্ট (hint): "এই ফাংশনটি (function) খুবই ছোট (tiny) — অনুগ্রহ করে একে সত্যিকারের কোনো ফাংশনে কল (call) করার পরিবর্তে, এর কল সাইটে (call site) সরাসরি এর বডিটিকে (body) পেস্ট (paste) করে দিন।" আধুনিক কম্পাইলারগুলো (Modern compilers) মূলত বেশিরভাগ সময়েই এগুলো নিজেরা (own) নিজেই সিদ্ধান্ত (decide) নিয়ে থাকে, তাই এই inline-টি বেশিরভাগ সময়ই শুধু বিভিন্ন লিঙ্কার এরর (linker errors) এড়ানোর (avoid) জন্যই বিভিন্ন হেডার-ফাইলের (header-file) ফাংশনে ব্যবহার করা হয়ে থাকে。
সি++১৪-এ (C++14) auto রিটার্ন টাইপগুলো (return types) নিয়ে আসা হয়েছিল — এটি মূলত এর return স্টেটমেন্ট (statement) থেকেই এর রিটার্ন টাইপটিকে (return type) অনুমান (deduces) করতে পারে। যা মূলত যেকোনো টেমপ্লেট (templates) এবং সাধারণ কিছু ফাংশনের (simple functions) জন্য বেশ ভালো কাজ (Handy) করে থাকে।
ল্যাম্বডাস (Lambdas) — উড়ন্ত ফাংশন বা Functions on the Fly
ল্যাম্বডা সিনট্যাক্স চিট শিট (Lambda Syntax Cheat Sheet)
এদের সাধারণ ফর্মগুলো বা রূপগুলো (general form) হলো: [capture](parameters) -> return_type { body }
[]— এটি মূলত বাইরের কোনো স্কোপ (outside scope) থেকে কিছুই ক্যাপচার (capture) করে না (nothing)[x]— এটি মূলত ভ্যালুর সাহায্যে (by value)x-কে ক্যাপচার (capture) বা কপি করে নেয়[&x]— এটি মূলত রেফারেন্সের সাহায্যে (by reference)x-কে ক্যাপচার করে নেয়[=]— এটি মূলত ভ্যালুর সাহায্যে সবকিছুকেই (everything) ক্যাপচার করে নেয়[&]— এটি মূলত রেফারেন্সের সাহায্যে সবকিছুকেই (everything) ক্যাপচার করে নেয়
ল্যাম্বডাগুলো (Lambdas) বিশেষত বিভিন্ন এসটিএল অ্যালগরিদমগুলোর (STL algorithms) সাথে বেশি কার্যকর (useful) হয়ে থাকে, যেমন sort, for_each, find_if, এবং count_if-এর মতো ফাংশনগুলো।