প্রায় প্রতিটি সি ++ রিসোর্সে আমি দেখেছি যে এই ধরণের জিনিস নিয়ে আলোচনা করে আমাকে বলে যে আমার আরটিটিআই (রান-টাইম টাইপ সনাক্তকরণ) ব্যবহারের ক্ষেত্রে পলিমারফিক পদ্ধতির পছন্দ করা উচিত। সাধারণভাবে, আমি এই ধরণের পরামর্শকে গুরুত্ব সহকারে নিই, এবং যুক্তিটি চেষ্টা করার চেষ্টা করব এবং বোঝার চেষ্টা করব - সর্বোপরি, সি ++ একটি শক্তিশালী জন্তু এবং এর সম্পূর্ণ গভীরতায় বোঝা শক্ত। তবে, এই নির্দিষ্ট প্রশ্নের জন্য, আমি একটি ফাঁকা অঙ্কন করছি এবং ইন্টারনেট কী ধরণের পরামর্শ দিতে পারে তা দেখতে চাই। প্রথমে আরটিটিআইকে "ক্ষতিকারক" বলে বিবেচনা করা হচ্ছে এমন সাধারণ কারণগুলির তালিকা দিয়ে আমি এ পর্যন্ত যা শিখেছি তার সংক্ষিপ্ত বিবরণ দেখি:
কিছু সংকলক এটি ব্যবহার করে না / আরটিটিআই সর্বদা সক্ষম হয় না
আমি সত্যিই এই যুক্তি কিনতে না। এটি বলার মতো যে আমার সি ++ 14 বৈশিষ্ট্যগুলি ব্যবহার করা উচিত নয়, কারণ সেখানে এমন সংকলক রয়েছে যা এটি সমর্থন করে না। এবং তবুও, কেউ আমাকে সি ++ 14 বৈশিষ্ট্য ব্যবহার থেকে নিরুৎসাহিত করবে না। বেশিরভাগ প্রকল্পের তারা ব্যবহার করছে এমন সংকলক এবং কীভাবে এটি কনফিগার করা হয়েছে তার উপর প্রভাব ফেলবে। এমনকি জিসিসি ম্যানপেজটি উদ্ধৃত করে:
-fno-rttiসি ++ রান-টাইম ধরণের সনাক্তকরণ বৈশিষ্ট্যগুলি (গতিশীল_কাস্ট এবং টাইপড) ব্যবহারের জন্য ভার্চুয়াল ফাংশন সহ প্রতিটি শ্রেণীর সম্পর্কে তথ্য উত্পন্নকরণকে অক্ষম করুন। আপনি যদি ভাষার সেই অংশগুলি ব্যবহার না করেন তবে আপনি এই পতাকা ব্যবহার করে কিছু জায়গা বাঁচাতে পারবেন। মনে রাখবেন যে ব্যতিক্রম হ্যান্ডলিং একই তথ্য ব্যবহার করে তবে G ++ এটি প্রয়োজনীয় হিসাবে উত্পন্ন করে। ডায়নামিক_কাস্ট অপারেটরটি এখনও সেই কাস্টগুলির জন্য ব্যবহার করা যেতে পারে যা রান-টাইম ধরণের তথ্যের প্রয়োজন হয় না, অর্থাত "" অকার্যকর * "বা সংক্ষিপ্ত বেস শ্রেণিতে ক্যাসেটগুলির প্রয়োজন হয় না।
এটি আমাকে যা বলে তা যদি আমি আরটিটিআই ব্যবহার না করি তবে আমি এটি অক্ষম করতে পারি। এটি বলার মতো, আপনি যদি বুস্ট ব্যবহার না করেন তবে আপনাকে এর সাথে লিঙ্ক করতে হবে না। কেউ যে মামলায় সংকলন করছে তার জন্য আমাকে পরিকল্পনা করার দরকার নেই -fno-rtti। এছাড়াও, সংকলকটি এক্ষেত্রে উচ্চস্বরে এবং পরিষ্কার হয়ে যাবে।
এটির জন্য অতিরিক্ত মেমরি খরচ হয় / ধীর হতে পারে
যখনই আমি আরটিটিআই ব্যবহার করতে প্ররোচিত হই, তার অর্থ আমার শ্রেণির কিছু ধরণের তথ্য বা বৈশিষ্ট্য অ্যাক্সেস করা দরকার। যদি আমি কোনও সমাধান প্রয়োগ করি যা আরটিটিআই ব্যবহার করে না, তবে এর অর্থ সাধারণত এই তথ্যগুলি সংরক্ষণ করার জন্য আমাকে আমার ক্লাসে কিছু ক্ষেত্র যুক্ত করতে হবে, তাই স্মৃতিশক্তির যুক্তিটি একদম শূন্য (আমি আরও নীচে এর উদাহরণ দেব)।
একটি গতিশীল_কাস্ট সত্যিই ধীর হতে পারে। যদিও গতি-সমালোচনামূলক পরিস্থিতিতে এটি ব্যবহার না করা সাধারণত উপায় রয়েছে। এবং আমি বিকল্পটি বেশ দেখতে পাচ্ছি না। এই এসও উত্তরটি টাইপটি সংরক্ষণ করতে বেস ক্লাসে সংজ্ঞায়িত এনাম ব্যবহার করার পরামর্শ দেয়। এটি কেবল তখনই কাজ করে যদি আপনি আপনার সমস্ত উত্সযুক্ত ক্লাসকে অগ্রাধিকার জানেন। এটি বেশ বড় "যদি"!
সেই উত্তর থেকে এটিও মনে হয় আরটিটিআইয়ের ব্যয়ও পরিষ্কার নয়। বিভিন্ন ব্যক্তি বিভিন্ন জিনিস পরিমাপ করে।
মার্জিত পলিমারফিক ডিজাইনগুলি আরটিটিআইকে অপ্রয়োজনীয় করে তুলবে
এই ধরণের পরামর্শ আমি গুরুত্ব সহকারে নিই। এই ক্ষেত্রে, আমি কেবল আমার আরটিটিআই ব্যবহারের ক্ষেত্রে ভাল নন-আরটিটিআই সলিউশন নিয়ে আসতে পারি না। আমাকে একটি উদাহরণ প্রদান করুন:
বলুন আমি কোনও ধরণের অবজেক্টের গ্রাফ পরিচালনা করতে একটি গ্রন্থাগার লিখছি। আমি আমার লাইব্রেরিটি ব্যবহার করার সময় ব্যবহারকারীদের তাদের নিজস্ব প্রকার তৈরি করার অনুমতি দিতে চাই (যাতে এনাম পদ্ধতিটি উপলভ্য নয়)। আমার নোডের জন্য আমার একটি বেস ক্লাস রয়েছে:
class node_base
{
public:
node_base();
virtual ~node_base();
std::vector< std::shared_ptr<node_base> > get_adjacent_nodes();
};
এখন, আমার নোড বিভিন্ন ধরণের হতে পারে। এগুলো কেমন:
class red_node : virtual public node_base
{
public:
red_node();
virtual ~red_node();
void get_redness();
};
class yellow_node : virtual public node_base
{
public:
yellow_node();
virtual ~yellow_node();
void set_yellowness(int);
};
জাহান্নাম, এগুলির মধ্যে একটিও কেন নয়:
class orange_node : public red_node, public yellow_node
{
public:
orange_node();
virtual ~orange_node();
void poke();
void poke_adjacent_oranges();
};
শেষ ফাংশন আকর্ষণীয়। এটি লেখার জন্য এখানে একটি উপায়:
void orange_node::poke_adjacent_oranges()
{
auto adj_nodes = get_adjacent_nodes();
foreach(auto node, adj_nodes) {
// In this case, typeid() and static_cast might be faster
std::shared_ptr<orange_node> o_node = dynamic_cast<orange_node>(node);
if (o_node) {
o_node->poke();
}
}
}
এটি সমস্ত পরিষ্কার এবং পরিষ্কার বলে মনে হচ্ছে। আমাকে এমন বৈশিষ্ট্য বা পদ্ধতিগুলি সংজ্ঞায়িত করতে হবে না যেখানে আমার তাদের প্রয়োজন হয় না, বেস নোড শ্রেণিটি ঝুঁকিতে থাকতে পারে এবং বোঝাতে পারে। আরটিটিআই ছাড়া আমি কোথায় শুরু করব? সম্ভবত আমি বেস শ্রেণিতে একটি নোড_ টাইপ বৈশিষ্ট্য যুক্ত করতে পারি:
class node_base
{
public:
node_base();
virtual ~node_base();
std::vector< std::shared_ptr<node_base> > get_adjacent_nodes();
private:
std::string my_type;
};
স্ট্যান্ডিং :: স্ট্রিং কি কোনও ধরণের জন্য ভাল ধারণা? হয়তো না, তবে আমি আর কি ব্যবহার করতে পারি? একটি সংখ্যা তৈরি করুন এবং আশা করুন যে কেউ এখনও এটি ব্যবহার করছে না? এছাড়াও, আমার কমলা_নোডের ক্ষেত্রে, যদি আমি red_node এবং হলুদ_নোড থেকে পদ্ধতিগুলি ব্যবহার করতে চাই? আমি নোড প্রতি একাধিক ধরণের সঞ্চয় করতে হবে? এটা জটিল মনে হচ্ছে।
উপসংহার
এই উদাহরণগুলি অত্যধিক জটিল বা অস্বাভাবিক বলে মনে হচ্ছে না (আমি আমার দিনের কাজের মতোই কিছু বিষয়ে কাজ করছি, যেখানে নোডগুলি এমন সত্যিকারের হার্ডওয়্যারকে উপস্থাপন করে যা সফ্টওয়্যারটির মাধ্যমে নিয়ন্ত্রিত হয়ে যায় এবং যা তারা কী তার উপর নির্ভর করে খুব আলাদা জিনিস করে)। তবুও আমি টেমপ্লেট বা অন্যান্য পদ্ধতিতে এটি করার কোনও পরিষ্কার উপায় জানতাম না। দয়া করে মনে রাখবেন যে আমি সমস্যাটি বোঝার চেষ্টা করছি, আমার উদাহরণটি রক্ষা করছি না। যেমন এইরকম উত্তর দেন আমি উপরের লিঙ্ক এবং পৃষ্ঠাগুলির আমার পড়া উপর উইকিবই এই পৃষ্ঠার আমি RTTI অপব্যবহার করছি সুপারিশ বলে মনে হচ্ছে, কিন্তু আমি কেন শিখতে চাই।
সুতরাং, আমার মূল প্রশ্নে ফিরে আসুন: আরটিটিআই ব্যবহারের চেয়ে কেন 'খাঁটি বহুবিকৃতি' বেশি পছন্দযোগ্য?
node_baseএটি একটি লাইব্রেরির অংশ এবং ব্যবহারকারীরা তাদের নিজস্ব নোড প্রকার তৈরি করবেন। তারপরে তারা অন্য কোনও সমাধানের অনুমতি দেওয়ার জন্য সংশোধন করতে পারবেন নাnode_base , সুতরাং আরটিটিআই তখন তাদের সেরা বিকল্প হয়ে উঠবে। অন্যদিকে, এই জাতীয় গ্রন্থাগারটি ডিজাইনের অন্যান্য উপায় রয়েছে যাতে আরটিটিআই ব্যবহার করার প্রয়োজন ছাড়াই নতুন নোড প্রকারগুলি আরও মার্জিতভাবে ফিট করতে পারে (এবং নতুন নোডের নকশার অন্যান্য উপায়ও) too