পলিমারফিজমের জন্য / প্রয়োজনীয়তাগুলি বোঝা
পলিমারফিজমটি বোঝার জন্য - যেহেতু শব্দটি কম্পিউটিং সায়েন্সে ব্যবহৃত হয় - এটি এর সাধারণ ব্যাখ্যা এবং এর সংজ্ঞা থেকে শুরু করতে সহায়তা করে। বিবেচনা:
Type1 x;
Type2 y;
f(x);
f(y);
এখানে f()
কিছু অপারেশন করা এবং মান x
এবং y
ইনপুট হিসাবে দেওয়া হচ্ছে ।
পলিমারফিজম প্রদর্শন f()
করতে , স্বতন্ত্র টাইপ-উপযুক্ত কোড সন্ধান এবং সম্পাদন করতে অবশ্যই কমপক্ষে দুটি স্বতন্ত্র প্রকারের (যেমন int
এবং double
) মানগুলির সাথে পরিচালনা করতে সক্ষম হতে হবে ।
বহুবর্ষের জন্য সি ++ প্রক্রিয়া +
স্পষ্টত প্রোগ্রামার-নির্দিষ্ট পলিমারফিজম
আপনি এটি লিখতে পারেন f()
যে এটি নিম্নলিখিত যে কোনও উপায়ে একাধিক প্রকারে পরিচালনা করতে পারে:
প্রাক-প্রক্রিয়াকরণ:
#define f(X) ((X) += 2)
// (note: in real code, use a longer uppercase name for a macro!)
ওভারলোডিং:
void f(int& x) { x += 2; }
void f(double& x) { x += 2; }
টেমপ্লেট:
template <typename T>
void f(T& x) { x += 2; }
ভার্চুয়াল প্রেরণ:
struct Base { virtual Base& operator+=(int) = 0; };
struct X : Base
{
X(int n) : n_(n) { }
X& operator+=(int n) { n_ += n; return *this; }
int n_;
};
struct Y : Base
{
Y(double n) : n_(n) { }
Y& operator+=(int n) { n_ += n; return *this; }
double n_;
};
void f(Base& x) { x += 2; } // run-time polymorphic dispatch
অন্যান্য সম্পর্কিত প্রক্রিয়া
অন্তর্নির্মিত ধরণের, স্ট্যান্ডার্ড রূপান্তরগুলি এবং ingালাই / জবরদস্তির জন্য সংকলক দ্বারা সরবরাহিত বহুগুণ সম্পর্কে পরে সম্পূর্ণতার জন্য আলোচনা করা হয়েছে:
- এগুলি যে কোনওভাবেই স্বজ্ঞাতভাবে বোঝা যায় (" ওহ, সেই " প্রতিক্রিয়াটির নিশ্চয়তা),
- তারা উপরোক্ত প্রক্রিয়াগুলি এবং প্রয়োজনীয় ব্যবহারের প্রান্তিকতা এবং ব্যবহারে নির্বিঘ্নে প্রভাব ফেলে
- ব্যাখ্যা আরও গুরুত্বপূর্ণ ধারণা থেকে একটি fidly বিচ্যুতি।
পরিভাষা
আরও শ্রেণিবিন্যাস
উপরের পলিমারফিক পদ্ধতিগুলি দেওয়া, আমরা তাদের বিভিন্ন উপায়ে শ্রেণিবদ্ধ করতে পারি:
1 - টেমপ্লেটগুলি অত্যন্ত নমনীয়। SFINAE (আরও দেখুন std::enable_if
) কার্যকরভাবে প্যারামেট্রিক পলিমারফিজমের জন্য বেশ কয়েকটি সেট প্রত্যাশার মঞ্জুরি দেয়। উদাহরণস্বরূপ, আপনি এনকোড করতে পারেন যে আপনি যে ধরণের ডেটা প্রক্রিয়াকরণ করছেন তাতে কোনও .size()
সদস্য ব্যবহার করার পরে আপনি একটি ফাংশন ব্যবহার করবেন, অন্যথায় অন্য কোনও ফাংশনটির প্রয়োজন নেই .size()
(তবে সম্ভবত কিছুটা ক্ষতিগ্রস্থ হচ্ছে - যেমন ধীর গতিতে ব্যবহার করুন strlen()
বা প্রিন্টিং হিসাবে নয় লগতে একটি বার্তা দরকারী)। নির্দিষ্ট পরামিতিগুলির সাথে টেম্পলেটটি ইনস্ট্যান্ট করা হলে আপনি কিছু প্যারামিটারগুলি প্যারামিটারিক ( আংশিক টেম্পলেট বিশেষায়িতকরণ ) না রেখে ( পুরো বিশেষায়িতকরণ ) ছেড়ে দিয়েও অ্যাড-হক আচরণগুলি নির্দিষ্ট করতে পারেন ।
"বহুরুপী"
আলফ স্টেইনবাচ মন্তব্য করেছেন যে সি ++ স্ট্যান্ডার্ড পলিমারফিক কেবল ভার্চুয়াল প্রেরণাদি ব্যবহার করে রান-টাইম পলিমারফিজমকে বোঝায়। জেনারেল কমপ সী। সি ++ স্রষ্টা বাজনার স্ট্রস্ট্রপের গ্লসারি ( http://www.stroustrup.com/glossary.html ) অনুসারে অর্থটি আরও অন্তর্ভুক্ত রয়েছে :
পলিমারফিজম - বিভিন্ন ধরণের সত্তাকে একক ইন্টারফেস সরবরাহ করে। ভার্চুয়াল ফাংশনগুলি একটি বেস ক্লাস দ্বারা সরবরাহিত ইন্টারফেসের মাধ্যমে গতিময় (রান-টাইম) পলিমারফিজম সরবরাহ করে। অতিরিক্ত লোড ফাংশন এবং টেমপ্লেটগুলি স্ট্যাটিক (সংকলন-সময়) পলিমারফিজম সরবরাহ করে। টিসি ++ পিএল 12.2.6, 13.6.1, ডি ও ই 2.9।
এই উত্তর - প্রশ্নের মতো - কম্পের সাথে সি ++ বৈশিষ্ট্য সম্পর্কিত। সী। পরিভাষা।
আলোচনা
সি ++ স্ট্যান্ডার্ড সহ কম্পের চেয়ে "পলিমারফিজম" এর সংকীর্ণ সংজ্ঞা ব্যবহার করে। সী। সম্প্রদায়, আপনার শ্রোতাদের বিবেচনা করে পারস্পরিক বোঝাপড়া নিশ্চিত করার জন্য ...
- দ্ব্যর্থহীন পরিভাষা ব্যবহার করে ("আমরা কি এই কোডটি অন্য ধরণের জন্য পুনরায় ব্যবহারযোগ্য করতে পারি?" বা "আমরা কি এই কোডটি বহুরূপী করতে পারি?") এর পরিবর্তে, "বা আমরা কি ভার্চুয়াল প্রেরণ ব্যবহার করতে পারি?"), এবং / অথবা
- পরিষ্কারভাবে আপনার পরিভাষা সংজ্ঞা।
তবুও, দুর্দান্ত সি ++ প্রোগ্রামার হওয়ার পক্ষে কী গুরুত্বপূর্ণ তা বোঝা যাচ্ছে যে পলিমারফিজম আপনার জন্য আসলে কী করছে ...
আপনাকে একবার "অ্যালগরিদমিক" কোড লিখতে দিন এবং তারপরে এটিকে অনেক ধরণের ডেটাতে প্রয়োগ করতে পারেন
... এবং তারপরে বিভিন্ন পলিমারফিক পদ্ধতিগুলি আপনার প্রকৃত প্রয়োজনগুলির সাথে কীভাবে মেলে সে সম্পর্কে খুব সচেতন হন।
রান-টাইম পলিমারফিজম স্যুট:
- ইনপুটটি কারখানার পদ্ধতি দ্বারা প্রক্রিয়াজাত করা হয় এবং
Base*
এস এর মাধ্যমে পরিচালিত ভিন্নজাতীয় বস্তু সংগ্রহ হিসাবে ছড়িয়ে পড়ে ,
- কনফিগারেশন ফাইল, কমান্ড লাইন সুইচ, ইউআই সেটিংস ইত্যাদির উপর ভিত্তি করে রানটাইম এ নির্বাচন করা বাস্তবায়ন,
- স্টেট মেশিনের ধরণ হিসাবে রানটাইম সময়ে বাস্তবায়ন বিভিন্ন রকম হয়।
রান-টাইম পলিমারফিজমের জন্য যখন স্পষ্ট ড্রাইভার নেই, তখন কমপাইল-টাইম বিকল্পগুলি প্রায়শই পছন্দনীয়। বিবেচনা:
- টেম্প্লেটেড ক্লাসগুলির সংকলন-যা-বলা হয় তা রানটাইম ব্যর্থ ফ্যাট ইন্টারফেসের চেয়ে ভাল
- SFINAE
- CRTP
- অপ্টিমাইজেশন (ইনলাইনিং এবং ডেড কোড এলিমিনেশন, লুপ আন্রোলিং, স্ট্যাটিক স্ট্যাক-ভিত্তিক অ্যারে বনাম হিপ সহ অনেকগুলি)
__FILE__
,, __LINE__
স্ট্রিং আক্ষরিক সম্মিলন এবং ম্যাক্রোর অন্যান্য অনন্য ক্ষমতা (যা মন্দ থেকে যায় ;-))
- টেমপ্লেট এবং ম্যাক্রো পরীক্ষার শব্দার্থিক ব্যবহার সমর্থিত তবে কৃত্রিমভাবে সেই সমর্থন কীভাবে সরবরাহ করা যায় তা সীমাবদ্ধ করবেন না (যেমন ভার্চুয়াল প্রেরণ সদস্যের ফাংশনটির ওভাররাইডগুলির সাথে সঠিকভাবে মিলে যাওয়ার প্রয়োজন হয়)
পলিমারফিজম সমর্থনকারী অন্যান্য প্রক্রিয়া
প্রতিশ্রুতি অনুসারে, সম্পূর্ণতার জন্য বেশ কয়েকটি পেরিফেরিয়াল বিষয়গুলি কভার করা হয়েছে:
- সংকলক-সরবরাহ ওভারলোড
- ধর্মান্তর
- কাস্ট / বলপ্রয়োগ
এই উত্তরটি পলিমারফিক কোড - বিশেষত প্যারামেট্রিক পলিমারফিজম (টেমপ্লেটস এবং ম্যাক্রোগুলি )কে শক্তিশালীকরণ ও সরলকরণের জন্য কীভাবে উপরের সংমিশ্রণটির একটি আলোচনার সাথে শেষ হয়েছে।
টাইপ-নির্দিষ্ট ক্রিয়াকলাপগুলিতে ম্যাপিংয়ের প্রক্রিয়া
> অন্তর্নিহিত সংকলক-সরবরাহ ওভারলোড
ধারণামূলকভাবে, সংকলক বিল্টিন টাইপের জন্য অনেক অপারেটরকে ওভারলোড করে । এটি ব্যবহারকারী-নির্দিষ্ট ওভারলোডিং থেকে ধারণাগতভাবে পৃথক নয়, তবে এটি সহজেই উপেক্ষা করার কারণে তালিকাবদ্ধ রয়েছে। উদাহরণস্বরূপ, যদি আপনি যোগ করতে পারেন int
s এবং double
একই স্বরলিপি ব্যবহার র x += 2
এবং কম্পাইলার উত্পাদন করে:
- টাইপ-নির্দিষ্ট সিপিইউ নির্দেশাবলী
- একই ধরণের ফলাফল।
ওভারলোডিং এর পরে নির্বিঘ্নে ব্যবহারকারী-সংজ্ঞায়িত প্রকারগুলিতে প্রসারিত হয়:
std::string x;
int y = 0;
x += 'c';
y += 'c';
প্রাথমিক ধরণের জন্য সংকলক দ্বারা সরবরাহিত ওভারলোডগুলি উচ্চ-স্তরের (3 জিএল +) কম্পিউটারের ভাষায় প্রচলিত এবং বহুকর্মের স্পষ্ট আলোচনা সাধারণত আরও কিছু বোঝায়। (2 জিএল - সমাবেশের ভাষাগুলি - প্রায়শই প্রোগ্রামারকে বিভিন্ন ধরণের জন্য স্পষ্টভাবে বিভিন্ন মিমোনমিক্স ব্যবহার করতে হয়))
> স্ট্যান্ডার্ড রূপান্তর
সি ++ স্ট্যান্ডার্ডের চতুর্থ বিভাগটি স্ট্যান্ডার্ড রূপান্তরগুলি বর্ণনা করে।
প্রথম পয়েন্টটি সুন্দরভাবে সংক্ষিপ্ত করে (পুরানো খসড়া থেকে - আশা করি এখনও যথেষ্ট পরিমাণে সঠিক):
-1- স্ট্যান্ডার্ড রূপান্তরগুলি অন্তর্নির্মিত ধরণের জন্য সংজ্ঞাযুক্ত অন্তর্নিহিত রূপান্তর। ক্লজ রূপে এই জাতীয় রূপান্তরগুলির পুরো সেটটি গণনা করা হয়। একটি স্ট্যান্ডার্ড রূপান্তর ক্রমটি নিম্নলিখিত ক্রমে মানক রূপান্তরগুলির একটি ক্রম:
নিম্নলিখিত সেট থেকে শূন্য বা একটি রূপান্তর: লভ্যালু-থেকে-র্যালুয়ে রূপান্তর, অ্যারে-টু-পয়েন্টার রূপান্তর এবং ফাংশন-টু-পয়েন্টার রূপান্তর।
শূন্য বা নিম্নলিখিত রূপ থেকে একটি রূপান্তর: অবিচ্ছেদ্য প্রচার, ভাসমান পয়েন্ট প্রচার, অবিচ্ছেদ্য রূপান্তরগুলি, ভাসমান পয়েন্ট রূপান্তরগুলি, ভাসমান-ইন্টিগ্রাল রূপান্তরগুলি, পয়েন্টার রূপান্তরগুলি, সদস্য রূপান্তরগুলিতে পয়েন্টার এবং বুলিয়ান রূপান্তর।
জিরো বা একটি যোগ্যতার রূপান্তর।
[দ্রষ্টব্য: একটি আদর্শ রূপান্তর ক্রমটি খালি থাকতে পারে, অর্থাত্ এতে কোনও রূপান্তর থাকতে পারে না। ] প্রয়োজনীয় গন্তব্য প্রকারে রূপান্তর করার জন্য যদি প্রয়োজন হয় তবে একটি অভিব্যক্তিটির কাছে একটি আদর্শ রূপান্তর ক্রম প্রয়োগ করা হবে।
এই রূপান্তরগুলি কোডের অনুমতি দেয় যেমন:
double a(double x) { return x + 2; }
a(3.14);
a(42);
আগের পরীক্ষা প্রয়োগ করা:
বহুমুখী হতে, [ a()
] অবশ্যই কমপক্ষে দুটি স্বতন্ত্র ধরণের (যেমন int
এবং double
) মানগুলির সাথে পরিচালনা করতে সক্ষম হবে , টাইপ-উপযুক্ত কোডটি সন্ধান এবং সম্পাদন করতে হবে ।
a()
নিজেই কোড বিশেষভাবে চালায় double
এবং তাই বহুকোষী নয় ।
কিন্তু, a()
সংকলকটির দ্বিতীয় কলটিতে রূপান্তর 42
করতে কোনও "ভাসমান পয়েন্ট প্রচার" (স্ট্যান্ডার্ড §4) এর জন্য টাইপ-উপযুক্ত কোড উত্পন্ন করতে জানে 42.0
। অতিরিক্ত কোডটি কলিং ফাংশনে রয়েছে। আমরা উপসংহারে এর তাত্পর্য আলোচনা করব।
> জবর, কাস্ট, অন্তর্নিহিত নির্মাতারা ruct
এই প্রক্রিয়াগুলি ব্যবহারকারী-সংজ্ঞায়িত ক্লাসগুলিকে বিল্টিন ধরণের 'স্ট্যান্ডার্ড রূপান্তরগুলির অনুরূপ আচরণগুলি নির্দিষ্ট করার মঞ্জুরি দেয়। চল একটু দেখি:
int a, b;
if (std::cin >> a >> b)
f(a, b);
এখানে, std::cin
রূপান্তর অপারেটরের সাহায্যে অবজেক্টটি বুলিয়ান প্রসঙ্গে মূল্যায়ন করা হয়। উপরের বিষয়টিতে এটি স্ট্যান্ডার্ড রূপান্তরগুলি থেকে "ইন্টিগ্রাল প্রচার" এবং এটিকে ধারণাগতভাবে গোষ্ঠীভুক্ত করা যেতে পারে।
অন্তর্ভুক্ত নির্মাতারা কার্যকরভাবে একই কাজ করে তবে কাস্ট-টু টাইপ দ্বারা নিয়ন্ত্রিত হয়:
f(const std::string& x);
f("hello"); // invokes `std::string::string(const char*)`
সংকলন সরবরাহকৃত ওভারলোড, রূপান্তর এবং জবরদস্তির প্রভাব
বিবেচনা:
void f()
{
typedef int Amount;
Amount x = 13;
x /= 2;
std::cout << x * 1.1;
}
x
বিভাগটি চলাকালীন আমরা যদি এই পরিমাণটি একটি আসল সংখ্যা হিসাবে বিবেচনা করতে চাই (অর্থাত্ 6 এর চেয়ে আরও 6.5 হওয়া উচিত) তবে আমাদের কেবল পরিবর্তিত হওয়া দরকার typedef double Amount
।
এটি দুর্দান্ত, তবে কোডটি স্পষ্টভাবে "সঠিকভাবে" টাইপ করা খুব বেশি কাজ হত না :
void f() void f()
{ {
typedef int Amount; typedef double Amount;
Amount x = 13; Amount x = 13.0;
x /= 2; x /= 2.0;
std::cout << double(x) * 1.1; std::cout << x * 1.1;
} }
তবে, বিবেচনা করুন যে আমরা প্রথম সংস্করণটিকে একটি রূপান্তর করতে পারি template
:
template <typename Amount>
void f()
{
Amount x = 13;
x /= 2;
std::cout << x * 1.1;
}
এটি সেই "ছোট্ট সুবিধামত বৈশিষ্ট্যগুলি" এর কারণে এটি এত সহজেই হয় তত সহজেই ইনস্ট্যান্ট করা যায় int
বা হয় double
এবং যেমনটি কাজ করে তেমন কাজ করে। এই বৈশিষ্ট্যগুলি ব্যতীত আমাদের সুস্পষ্ট ক্যাসট, বৈশিষ্ট্য এবং / অথবা নীতি ক্লাস, কিছু শব্দাবলীর, ত্রুটি-ঝুঁকিপূর্ণ জগাখিচুড়ি যেমন দরকার:
template <typename Amount, typename Policy>
void f()
{
Amount x = Policy::thirteen;
x /= static_cast<Amount>(2);
std::cout << traits<Amount>::to_double(x) * 1.1;
}
সুতরাং, বিল্টিন ধরণের, স্ট্যান্ডার্ড রূপান্তরগুলি, ingালাই / জবরদস্তি / অন্তর্নিহিত কন্সট্রাক্টরগুলির জন্য সংকলক-সরবরাহকারী অপারেটর ওভারলোডিং - তারা সবাই পলিমারফিজমের জন্য সূক্ষ্ম সমর্থন অবদান রাখে। এই উত্তরের উপরের সংজ্ঞা থেকে তারা ম্যাপিংয়ের মাধ্যমে "টাইপ-উপযুক্ত কোডটি সন্ধান এবং সম্পাদন করে" সম্বোধন করে:
তারা না নিজেরাই বহুরুপী প্রেক্ষিতে স্থাপন, কিন্তু এই ধরনের প্রেক্ষিতে ভিতরে সাহায্যের ক্ষমতায়ন / প্রক্রিয়া সহজ কোড না।
আপনি প্রতারিত বোধ করতে পারেন ... এটি অনেকটা মনে হয় না। তাত্পর্যটি হ'ল প্যারাম্যাট্রিক পলিমর্ফিক প্রসঙ্গে (অর্থাত্ টেমপ্লেট বা ম্যাক্রোগুলির অভ্যন্তরে) আমরা একটি নির্বিচারে বড় ধরণের প্রকারকে সমর্থন করার চেষ্টা করছি তবে প্রায়শই অন্যান্য ক্রিয়াকলাপ, আক্ষরিক এবং ক্রিয়াকলাপগুলির জন্য তাদের উপর ক্রিয়াকলাপ প্রকাশ করতে চাই যা একটি ডিজাইন করা হয়েছিল প্রকারের ছোট সেট। অপারেশন / মান যৌক্তিকভাবে একই হয়ে গেলে এটি প্রতি-টাইপ ভিত্তিতে কাছাকাছি-অভিন্ন ফাংশন বা ডেটা তৈরির প্রয়োজনীয়তা হ্রাস করে। এই বৈশিষ্ট্যগুলি "সেরা চেষ্টা" এর মনোভাব যুক্ত করতে সহযোগিতা করে, সীমিত উপলব্ধ ফাংশন এবং ডেটা ব্যবহার করে স্বজ্ঞাতভাবে যা প্রত্যাশা করা হয় তা করে এবং যখন সত্যিকারের অস্পষ্টতা থাকে কেবল তখনই একটি ত্রুটি থামিয়ে দেয়।
এটি পলিমারফিক কোডকে সমর্থনকারী পলিমারফিক কোডের প্রয়োজনীয়তা সীমাবদ্ধ করতে সহায়তা করে, বহুবর্ষের ব্যবহারের চারপাশে একটি শক্ত জাল আঁকেন যাতে স্থানীয়করণ ব্যাপক ব্যবহারকে বাধ্যতামূলক করে না, এবং বহির্মুখীতার সুবিধাগুলি কার্যকরভাবে প্রয়োগের ব্যয় বহন না করে প্রয়োজনীয় হিসাবে উপলব্ধ করে তোলে সংকলন সময়, ব্যবহৃত ধরণের সমর্থন করার জন্য অবজেক্ট কোডে একই লজিক্যাল ফাংশনের একাধিক অনুলিপি রাখুন, এবং ইনলাইনিংয়ের বিপরীতে ভার্চুয়াল প্রেরণ করার সময় বা কমপক্ষে সংকলিত সংলগ্ন কলগুলির বিপরীতে সি ++ তে সাধারণত যেমন প্রোগ্রামারকে পলিমার্ফিজম ব্যবহার করা হয় সেই সীমানাগুলি নিয়ন্ত্রণ করতে প্রচুর স্বাধীনতা দেওয়া হয়।