একটি উত্তম পঠন হতে আমি কথোপকথনের আকারে আমার উত্তর পেয়েছি:
আমাদের ভার্চুয়াল ফাংশনগুলি কেন দরকার?
পলিমারফিজমের কারণে।
পলিমারফিজম কী?
একটি বেস পয়েন্টারটি উত্পন্ন ধরণের বস্তুগুলিকেও নির্দেশ করতে পারে।
পলিমারফিজমের এই সংজ্ঞাটি ভার্চুয়াল ফাংশনগুলির প্রয়োজনীয়তার দিকে পরিচালিত করে?
আচ্ছা, প্রথমদিকে বাঁধাইয়ের মাধ্যমে ।
তাড়াতাড়ি বাঁধাই কি?
সি ++ এ প্রারম্ভিক বাঁধাই (কম্পাইল-টাইম বাইন্ডিং) এর অর্থ প্রোগ্রামটি কার্যকর হওয়ার আগে একটি ফাংশন কল স্থির করা হয়।
তাই ...?
সুতরাং আপনি যদি কোনও ফাংশনের প্যারামিটার হিসাবে বেস টাইপটি ব্যবহার করেন তবে সংকলকটি কেবল বেস ইন্টারফেসটি স্বীকৃত করবে এবং আপনি যদি সেই ফাংশনটি উত্পন্ন শ্রেণি থেকে কোনও যুক্তি দিয়ে কল করেন তবে এটি কেটে ফেলা হবে, যা আপনি ঘটতে চান তা নয়।
যদি আমরা যা করতে চাই তা না হয় তবে কেন এটি অনুমোদিত?
কারণ আমাদের পলিমারফিজম দরকার!
পলিমারফিজমের সুবিধা কী?
আপনি একটি একক ফাংশনের প্যারামিটার হিসাবে বেস টাইপ পয়েন্টার ব্যবহার করতে পারেন এবং তারপরে আপনার প্রোগ্রামের রান-টাইমে আপনি কোনও একক ছাড়াই ডাইরফারেন্স ব্যবহার করে কোনও উদ্ভূত টাইপ ইন্টারফেসের (যেমন তাদের সদস্য ফাংশন) অ্যাক্সেস করতে পারবেন বেস পয়েন্টার
ভার্চুয়াল ফাংশনগুলি কীসের জন্য ভাল তা আমি এখনও জানি না ...! এবং এটি আমার প্রথম প্রশ্ন!
ঠিক আছে, কারণ আপনি খুব শীঘ্রই আপনার প্রশ্ন জিজ্ঞাসা করেছেন!
আমাদের ভার্চুয়াল ফাংশনগুলি কেন দরকার?
ধরে নিন যে আপনি একটি বেস পয়েন্টার সহ একটি ফাংশন বলেছেন, যার উত্পন্ন ক্লাসগুলির মধ্যে একটির সাথে কোনও বস্তুর ঠিকানা ছিল। যেমন আমরা উপরে এটি সম্পর্কে কথা বলেছি, রান-টাইমে, এই পয়েন্টারটি অবজ্ঞাপূর্ণ হয়ে যায়, এতদূর ভাল, তবে, আমরা আশা করি একটি পদ্ধতি (== একটি সদস্য ফাংশন) "আমাদের উত্পন্ন শ্রেণি থেকে" কার্যকর করা হবে! তবে, একই শ্রেণিটি (একই শিরোনামযুক্ত একটি) ইতিমধ্যে বেস শ্রেণিতে সংজ্ঞায়িত করা হয়েছে, সুতরাং আপনার প্রোগ্রামটি কেন অন্য পদ্ধতিটি বেছে নিতে বিরক্ত হবে? অন্য কথায় আমার অর্থ, আমরা সাধারণত এই ঘটনাটি দেখতে আগে যা করতে দেখতাম তা থেকে কীভাবে বলতে পারি?
সংক্ষিপ্ত উত্তরটি "বেসে একটি ভার্চুয়াল সদস্য ফাংশন", এবং আরও দীর্ঘ উত্তরটি হ'ল, "এই পদক্ষেপে, প্রোগ্রামটি যদি বেস শ্রেণিতে কোনও ভার্চুয়াল ফাংশন দেখে, এটি জানে (বুঝতে পারে) যে আপনি ব্যবহার করার চেষ্টা করছেন পলিমারফিজম "এবং তাই একই শিরোলেখের সাথে অন্য পদ্ধতি , তবে-এক্সপেক্টেড - একটি ভিন্ন বাস্তবায়ন সহ এটি আবিষ্কার করতে ( ভি-টেবিল , দেরীতে আবদ্ধের একটি রূপ ব্যবহার করে) উত্পন্ন ক্লাসগুলিতে যায় ।
আলাদা বাস্তবায়ন কেন?
তুমি মাথা নাক! একটি ভাল বই পড়তে যান !
ঠিক আছে, অপেক্ষা করুন অপেক্ষা করুন, কেন কেউ বেস পয়েন্টারগুলি ব্যবহার করতে বিরক্ত করবে, যখন সে কেবল ডাইরেক্টেড টাইপ পয়েন্টার ব্যবহার করতে পারে? আপনি বিচারক হন, এই সমস্ত মাথাব্যথা কি মূল্যবান? এই দুটি স্নিপেট দেখুন:
// 1:
Parent* p1 = &boy;
p1 -> task();
Parent* p2 = &girl;
p2 -> task();
// 2:
Boy* p1 = &boy;
p1 -> task();
Girl* p2 = &girl;
p2 -> task();
ঠিক আছে, যদিও আমি মনে করি 1 এখনও 2 এর চেয়ে ভাল তবে আপনি 1 টি এভাবে লিখতে পারেন:
// 1:
Parent* p1 = &boy;
p1 -> task();
p1 = &girl;
p1 -> task();
এবং তদ্ব্যতীত, আপনার সচেতন হওয়া উচিত যে এটি এখনও পর্যন্ত আমি আপনাকে যে সমস্ত বিষয় ব্যাখ্যা করেছি সেগুলির কেবলমাত্র একটি স্বীকৃত ব্যবহার। এর পরিবর্তে, উদাহরণস্বরূপ এমন একটি পরিস্থিতি ধরে নিন যাতে আপনি আপনার প্রোগ্রামে একটি ফাংশন রেখেছিলেন যা যথাক্রমে উত্পন্ন ক্লাসের প্রতিটি পদ্ধতি (getMonthBenefit ()) ব্যবহার করে:
double totalMonthBenefit = 0;
std::vector<CentralShop*> mainShop = { &shop1, &shop2, &shop3, &shop4, &shop5, &shop6};
for(CentralShop* x : mainShop){
totalMonthBenefit += x -> getMonthBenefit();
}
এখন, কোনও মাথাব্যথা ছাড়াই এটি আবার লেখার চেষ্টা করুন !
double totalMonthBenefit=0;
Shop1* branch1 = &shop1;
Shop2* branch2 = &shop2;
Shop3* branch3 = &shop3;
Shop4* branch4 = &shop4;
Shop5* branch5 = &shop5;
Shop6* branch6 = &shop6;
totalMonthBenefit += branch1 -> getMonthBenefit();
totalMonthBenefit += branch2 -> getMonthBenefit();
totalMonthBenefit += branch3 -> getMonthBenefit();
totalMonthBenefit += branch4 -> getMonthBenefit();
totalMonthBenefit += branch5 -> getMonthBenefit();
totalMonthBenefit += branch6 -> getMonthBenefit();
এবং প্রকৃতপক্ষে, এটি এখনও একটি স্বল্প উদাহরণ হতে পারে!