আরটিটিআই ব্যবহারের চেয়ে কেন 'খাঁটি পলিমারফিজম' বেশি পছন্দ?


106

প্রায় প্রতিটি সি ++ রিসোর্সে আমি দেখেছি যে এই ধরণের জিনিস নিয়ে আলোচনা করে আমাকে বলে যে আমার আরটিটিআই (রান-টাইম টাইপ সনাক্তকরণ) ব্যবহারের ক্ষেত্রে পলিমারফিক পদ্ধতির পছন্দ করা উচিত। সাধারণভাবে, আমি এই ধরণের পরামর্শকে গুরুত্ব সহকারে নিই, এবং যুক্তিটি চেষ্টা করার চেষ্টা করব এবং বোঝার চেষ্টা করব - সর্বোপরি, সি ++ একটি শক্তিশালী জন্তু এবং এর সম্পূর্ণ গভীরতায় বোঝা শক্ত। তবে, এই নির্দিষ্ট প্রশ্নের জন্য, আমি একটি ফাঁকা অঙ্কন করছি এবং ইন্টারনেট কী ধরণের পরামর্শ দিতে পারে তা দেখতে চাই। প্রথমে আরটিটিআইকে "ক্ষতিকারক" বলে বিবেচনা করা হচ্ছে এমন সাধারণ কারণগুলির তালিকা দিয়ে আমি এ পর্যন্ত যা শিখেছি তার সংক্ষিপ্ত বিবরণ দেখি:

কিছু সংকলক এটি ব্যবহার করে না / আরটিটিআই সর্বদা সক্ষম হয় না

আমি সত্যিই এই যুক্তি কিনতে না। এটি বলার মতো যে আমার সি ++ 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 অপব্যবহার করছি সুপারিশ বলে মনে হচ্ছে, কিন্তু আমি কেন শিখতে চাই।

সুতরাং, আমার মূল প্রশ্নে ফিরে আসুন: আরটিটিআই ব্যবহারের চেয়ে কেন 'খাঁটি বহুবিকৃতি' বেশি পছন্দযোগ্য?


9
আপনার পোকে কমলা উদাহরণটি সমাধান করার জন্য আপনি "অনুপস্থিত" (ভাষা বৈশিষ্ট্য হিসাবে) একাধিক প্রেরণ ("মাল্টিমেডথস") হবেন। সুতরাং, অনুকরণ করার উপায়গুলি অনুসন্ধান করা যা বিকল্প হতে পারে। সাধারণত, তাই দর্শনার্থী প্যাটার্ন ব্যবহার করা হয়।
ড্যানিয়েল জোর

1
টাইপ হিসাবে স্ট্রিং ব্যবহার করা খুব সহায়ক নয়। কিছু "টাইপ" শ্রেণীর উদাহরণের জন্য পয়েন্টার ব্যবহার করলে এটি দ্রুত হয় would তবে তারপরে আপনি মূলত আরটিটিআই যা করবে তা ম্যানুয়ালি করছেন।
ড্যানিয়েল জোর

4
@ মার্গারেটলুম না, এটি হবে না, আরটিটিআই মানে রানটাইম টাইপ ইনফরমেশন, যখন সিআরটিপি কেবলমাত্র টেমপ্লেট - স্ট্যাটিক প্রকারের জন্য।
এডিএমজেড

2
@ এমবিআর0 ডব্লিউএন: সমস্ত ইঞ্জিনিয়ারিং প্রক্রিয়া কিছু নিয়মের দ্বারা আবদ্ধ; প্রোগ্রামিং ব্যতিক্রম নয়। নিয়মগুলিকে দুটি বালতিতে বিভক্ত করা যেতে পারে: নরম বিধি (শল্ড) এবং কঠোর নিয়ম (আবশ্যক)। (একটি পরামর্শ / বিকল্প বালতিও রয়েছে (কুল্ড), তাই কথা বলতে)) পড়ুন কীভাবে সি / সি ++ স্ট্যান্ডার্ড (বা অন্য কোনও ইঞ্জিন স্ট্যান্ডার্ড, বাস্তবতার জন্য) সেগুলি কীভাবে সংজ্ঞায়িত করে। আমার অনুমান যে আপনার সমস্যাটি সত্যিকার অর্থে এসেছে যে আপনি "আরটিটিআই ব্যবহার করবেন না" একটি কঠোর নিয়ম হিসাবে ("আপনি আরটিটিআই ব্যবহার করবেন না") ভুল করেছেন। এটি আসলে একটি নরম নিয়ম ("আপনি আরটিটিআই ব্যবহার করবেন না") যার অর্থ যখনই সম্ভব

3
আমি লক্ষ করেছি যে প্রচুর উত্তরগুলি ধারণাটি নোট করে না যে আপনার উদাহরণ পরামর্শ দেয় যে node_baseএটি একটি লাইব্রেরির অংশ এবং ব্যবহারকারীরা তাদের নিজস্ব নোড প্রকার তৈরি করবেন। তারপরে তারা অন্য কোনও সমাধানের অনুমতি দেওয়ার জন্য সংশোধন করতে পারবেন নাnode_base , সুতরাং আরটিটিআই তখন তাদের সেরা বিকল্প হয়ে উঠবে। অন্যদিকে, এই জাতীয় গ্রন্থাগারটি ডিজাইনের অন্যান্য উপায় রয়েছে যাতে আরটিটিআই ব্যবহার করার প্রয়োজন ছাড়াই নতুন নোড প্রকারগুলি আরও মার্জিতভাবে ফিট করতে পারে (এবং নতুন নোডের নকশার অন্যান্য উপায়ও) too
ম্যাথু ওয়ালটন

উত্তর:


69

একটি ইন্টারফেস কোড বর্ণিত পরিস্থিতিতে ইন্টারঅ্যাক্ট করার জন্য একটি কি জানা প্রয়োজন তা বর্ণনা করে। একবার আপনি "আপনার সম্পূর্ণ ধরণের শ্রেণিবিন্যাস" দিয়ে ইন্টারফেসটি প্রসারিত করার পরে, আপনার ইন্টারফেস "পৃষ্ঠতল অঞ্চল" বিশাল আকার ধারণ করে, যা এটির পক্ষে যুক্তি আরও শক্ত করে তোলে ।

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

এখন প্রত্যেকটি যারা আপনার সম্পূর্ণ কমলা প্রকারের সাথে "কমলা" যুক্ত দম্পতি এবং সংজ্ঞাযুক্ত ইন্টারফেসের পরিবর্তে আপনার পুরো ব্যক্তিগত উদ্যানের সাথে স্পষ্টভাবে জুড়ে।

যদিও প্রথম নজরে এটি সমস্ত ক্লায়েন্টকে (যুক্ত করা am_I_orange) পরিবর্তন না করেই সীমিত ইন্টারফেসটি প্রসারিত করার দুর্দান্ত উপায়টির মতো দেখায় , পরিবর্তে যা ঘটতে থাকে তা হ'ল কোড বেসটিকে অস্পষ্ট করে এবং আরও সম্প্রসারণকে বাধা দেয় । বিশেষ কমলা রঙ সিস্টেমের কার্যকারিতার অন্তর্নিহিত হয়ে ওঠে এবং আপনাকে কমলাগুলির জন্য একটি "টাঙ্গেরিন" প্রতিস্থাপন তৈরি করতে বাধা দেয় যা ভিন্নভাবে প্রয়োগ করা হয় এবং সম্ভবত নির্ভরতা সরিয়ে দেয় বা অন্য কোনও সমস্যা মার্জিতভাবে সমাধান করে।

এর অর্থ এই নয় যে আপনার সমস্যাটি সমাধান করার জন্য আপনার ইন্টারফেসটি পর্যাপ্ত পরিমাণে থাকতে হবে। সেই দৃষ্টিকোণ থেকে, আপনার কেবল কমলা ঝুঁকতে হবে কেন এবং যদি তাই হয় তবে কেন ইন্টারফেসে কমলাভাব অনুপলব্ধ ছিল? আপনার যদি অ্যাড-হক যুক্ত করা যায় এমন কিছু ফিজি সেট ট্যাগ প্রয়োজন হয় তবে আপনি এটিকে আপনার প্রকারে যুক্ত করতে পারেন:

class node_base {
  public:
    bool has_tag(tag_name);

এটি আপনার ইন্টারফেসের সংক্ষিপ্তভাবে ব্রড ট্যাগ-ভিত্তিক নির্দিষ্ট করে বৃহত্তর সম্প্রসারণ সরবরাহ করে। আরটিটিআই এবং প্রয়োগের বিবরণ (এফ, "আপনি কীভাবে প্রয়োগ করবেন? কমলা টাইপের সাথে? ঠিক আছে আপনি পাশ করেছেন।") এর মাধ্যমে এটি না করে, এটি সম্পূর্ণ ভিন্ন বাস্তবায়নের মাধ্যমে সহজেই অনুকরণ করা কিছু দিয়ে এটি করে।

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

বাস্তবায়ন-ডিউপলড হওয়ার সময় এখন টেঞ্জারিন অবজেক্টগুলিতে কমলা ট্যাগ থাকতে পারে এবং পাশাপাশি খেলতেও পারে।

এটি এখনও একটি বিশাল জগাখিচুড়ির দিকে নিয়ে যেতে পারে তবে এটি কমপক্ষে বার্তাগুলি এবং উপাত্তগুলির একটি জগাখিচুড়ি, বাস্তবায়নক্রমক্রম নয়।

বিমূর্ততা হ্রাস এবং অপ্রাসঙ্গিকতা লুকানোর একটি খেলা। এটি স্থানীয়ভাবে যুক্তিযুক্ত কোডটি সহজ করে তোলে। আরটিটিআই বাস্তবায়ন বিশদে বিমূর্তির মাধ্যমে সরাসরি একটি গর্ত বিরক্ত করছে। এটি সমস্যার সমাধান সহজতর করতে পারে তবে এটি আপনাকে সহজেই খুব সহজেই একটি নির্দিষ্ট প্রয়োগের সাথে তালাবন্ধ করতে ব্যয় করে।


14
খুব শেষ অনুচ্ছেদের জন্য +1; আমি কেবল আপনার সাথে একমত হওয়ার কারণে নয়, এটি এখানে পেরেকের হাতুড়ি।

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

2
@ ফ্যালকো: এটিই হ'ল প্রথম সম্ভাবনা যা আমি উল্লেখ করেছি, ট্যাগের উপর ভিত্তি করে চেক না করা ingালাই। এখানে ট্যাগিং হ'ল নিজের খুব ভঙ্গুর এবং খুব ফলস্বরূপ গতিশীল ধরণের চেকিং স্কিম। যে কোনও সামান্য ক্লায়েন্ট কোড খারাপ ব্যবহার, এবং সি ++ এ এক ইউবি-জমিতে বন্ধ রয়েছে। আপনি জাভাতে যেমন পাবেন তেমন কোনও ব্যতিক্রম পাবেন না, তবে ক্র্যাশ এবং / বা ভুল ফলাফলের মতো অপরিজ্ঞাত আচরণ। অত্যন্ত অবিশ্বাস্য এবং বিপজ্জনক হওয়ার পাশাপাশি এটি আরও বুদ্ধিমান সি ++ কোডের তুলনায় অত্যন্ত চূড়ান্ত fficient আইওডাব্লু। অত্যন্ত তাই
চিয়ার্স এবং এইচটিএইচ - আলফ

1
UHM। :) যুক্তি ধরণের?
চিয়ার্স এবং এইচটিএইচ - আলফ

2
@ জোজআটএক্সজিএমই: কারণ "পলিমারফিজম" অর্থ বিভিন্ন ধরণের সাথে কাজ করতে সক্ষম হওয়া। আপনি যদি এটি দেখতে চান যে এটি কোনও নির্দিষ্ট ধরণের কিনা , ইতিমধ্যে বিদ্যমান টাইপ চেকের বাইরে আপনি পয়েন্টার / রেফারেন্সটি শুরু করার জন্য ব্যবহার করেছিলেন তবে আপনি পলিমারফিজমের পিছনে সন্ধান করছেন। আপনি বিভিন্ন ধরণের সাথে কাজ করছেন না; আপনি একটি নির্দিষ্ট ধরণের সাথে কাজ করছেন । হ্যাঁ, জাভাতে "(বড়) প্রকল্পগুলি" এটি করে। তবে তা জাভা ; ভাষা কেবল গতিময় বহুবর্ষকে মঞ্জুরি দেয়। সি ++ এর পাশাপাশি স্ট্যাটিক পলিমারফিজম রয়েছে। এছাড়াও, কেবল "বড়" কেউ এটিকে ভাল ধারণা দেয় না বলেই।
নিকল বোলাস

31

এই বা এই বৈশিষ্ট্যের বিরুদ্ধে সবচেয়ে বেশি নৈতিক অভিযান হ'ল বৈশিষ্ট্যটির উত্সত পর্যবেক্ষণ থেকে ঘটেছিল যে সেই বৈশিষ্ট্যের ভুল ধারণা নিয়ে ব্যবহারের একটি ছত্রাক রয়েছে ।

যেখানে নৈতিকতাবাদীরা ব্যর্থ হবেন তারা হ'ল তারা সমস্ত ব্যবহারের ভ্রান্ত ধারণা পোষণ করেছেন, এবং বাস্তবে বৈশিষ্ট্যগুলি একটি কারণে উপস্থিত রয়েছে।

তারা মনে করে সব: তারা কি আমি "সীসক জটিল" কল করার জন্য ব্যবহার করা আছে কল করছে স্বাভাবিকভাবে কাজ কারণ সব কল তারা মেরামতি করার আহবান জানানো হচ্ছে। বাস্তবতাটি হ'ল বেশিরভাগ ট্যাপগুলি ভালভাবে কাজ করে: আপনি কেবল তাদের জন্য কোনও প্লাম্বার কল করেন না!

একটি পাগল জিনিসটি ঘটতে পারে যখন কোনও প্রদত্ত বৈশিষ্ট্যটি ব্যবহার এড়ানোর জন্য, প্রোগ্রামাররা অনেকগুলি বয়লারপ্লিট কোড লিখেন প্রকৃতপক্ষে ব্যক্তিগতভাবে সেই বৈশিষ্ট্যটিকে পুনরায় প্রয়োগ করে। (আপনি কি কখনও এমন ক্লাসের সাথে সাক্ষাত করেছেন যা আরটিটিআই বা ভার্চুয়াল কল ব্যবহার করে না, তবে কোন প্রকৃত উত্পন্ন প্রকারটি তা ট্র্যাক করার জন্য কোনও মূল্য আছে? এটি আরটিটিআইয়ের ছদ্মবেশে পুনর্বিন্যাসের চেয়ে বেশি কিছু নয় ))

একটি সাধারণ ভাবে পলিমরফিজম সম্পর্কে ভাবতে নেই: IF(selection) CALL(something) WITH(parameters)। (দুঃখিত, তবে প্রোগ্রামিং, যখন বিমূর্তি উপেক্ষা করা যায়, তবে এগুলিই ঘটে)

ডিজাইন-টাইম (ধারণাগুলি) সংকলন-সময় (টেমপ্লেট-ছাড়ের ভিত্তিক), রান-টাইম (উত্তরাধিকার এবং ভার্চুয়াল ফাংশন-ভিত্তিক) বা ডেটা-চালিত (আরটিটিআই এবং স্যুইচিং) পলিমারফিজমের সিদ্ধান্ত নির্ভর করে যে কতগুলি সিদ্ধান্ত জানা যায় তার উপর নির্ভর করে উত্পাদনের প্রতিটি পর্যায়ে এবং প্রতিটি প্রসঙ্গে তারা কতটা পরিবর্তনশীল

ধারণাটি হ'ল:

আপনি যতটা অনুমান করতে পারবেন তত ত্রুটি ধরা এবং ততক্ষণে ব্যবহারকারীকে প্রভাবিত করতে থাকা বাগগুলি এড়ানো সম্ভব।

যদি সবকিছু স্থির থাকে (ডেটা সহ) আপনি টেমপ্লেট মেটা-প্রোগ্রামিং দিয়ে সবকিছু করতে পারেন। বাস্তবায়িত ধ্রুবকগুলিতে সংকলন হওয়ার পরে, পুরো প্রোগ্রামটি কেবলমাত্র একটি রিটার্ন বিবৃতিতে সিদ্ধ হয় যা ফলাফলটি ছড়িয়ে দেয় ।

যদি সংকলনের সময় এমন বেশ কয়েকটি কেস পরিচিত হয় তবে তাদের প্রকৃত তথ্য সম্পর্কে আপনি জানেন না তবে তাদের সংকলন-সময় পলিমারফিজম (মূলত সিআরটিপি বা অনুরূপ) সমাধান হতে পারে।

যদি কেসগুলির নির্বাচন ডেটা উপর নির্ভর করে (সংকলনযুক্ত জ্ঞাত মানগুলি নয়) এবং স্যুইচিং মনো-মাত্রিক হয় (কী করণীয় কেবলমাত্র একটি মানকে হ্রাস করা যায়) তবে ভার্চুয়াল ফাংশন ভিত্তিক প্রেরণ (বা সাধারণভাবে "ফাংশন পয়েন্টার টেবিলগুলি ") প্রয়োজন হয়.

যদি স্যুইচিংটি বহুমাত্রিক হয়, যেহেতু সি ++ তে কোনও দেশীয় একাধিক রানটাইম প্রেরণের অস্তিত্ব নেই, তবে আপনাকে যা করতে হবে:

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

যদি না শুধুমাত্র স্যুইচিং, তবে ক্রিয়াকলাপগুলিও জানা সময়ের সংকলন না হয় তবে স্ক্রিপ্টিং এবং পার্সিংয়ের প্রয়োজন হয়: ডেটা নিজেই তাদের উপর নেওয়া ক্রিয়াটি বর্ণনা করতে হবে।

এখন, যেহেতু আমি গণনা করেছি প্রতিটি ক্ষেত্রেই এটি অনুসরণ করে চলেছে তার একটি বিশেষ কেস হিসাবে দেখা যায়, আপনি উপরের-সর্বাধিক সমস্যার সাশ্রয়ী মূল্যের সমস্যাগুলির জন্য নীচের সর্বাধিক সমাধানটিকে গালি দিয়ে প্রতিটি সমস্যার সমাধান করতে পারেন।

এর কি যে moralization আসলে এড়াতে push কর্মের। তবে এর অর্থ এই নয় যে নীচের অংশে বেশিরভাগ ডোমেনে থাকার সমস্যা নেই!

আরটিটিআই-কে বাশ দেওয়া ঠিক তা ঠাট্টা করা, এটি চাপ দেওয়ার মতো ধাক্কা gotoদেওয়ার মতো । প্রোগ্রামারদের জন্য নয়, তোতার জন্য জিনিস।


প্রতিটি পদ্ধতির যে স্তরে প্রযোজ্য সেগুলির একটি ভাল অ্যাকাউন্ট। যদিও আমি "গোডেলাইজেশন" এর কথা শুনিনি - এটি কি অন্য কোনও নামে পরিচিত? আপনি সম্ভবত একটি লিঙ্ক বা আরও ব্যাখ্যা যোগ করতে পারেন? ধন্যবাদ :)
j_random_hacker

1
@ জেআর্যান্ডম_হ্যাকার: আমিও Godশ্বরিকরণের এই ব্যবহার সম্পর্কে আগ্রহী। একজন সাধারনত গডেলাইজেশনকে প্রথম হিসাবে বিবেচনা করে কিছু স্ট্রিং থেকে কিছু পূর্ণসংখ্যার সাথে ম্যাপিং করে এবং দ্বিতীয়ত, এই কৌশলটি ব্যবহার করে আনুষ্ঠানিক ভাষায় স্ব-রেফারেন্সিয়াল বিবৃতি তৈরি করে। ভার্চুয়াল প্রেরণের প্রসঙ্গে আমি এই শব্দটির সাথে অপরিচিত এবং আরও শিখতে চাই।
এরিক লিপার্ট

1
আসলে আমি এই শব্দটি অপব্যবহার করছি : গোডলের মতে, যেহেতু প্রতিটি পূর্ণসংখ্যা একটি পূর্ণসংখ্যার সাথে এন-পিলে (তার মূল উপাদানগুলির শক্তি) এবং প্রতিটি এন-পিলেস একটি পূর্ণসংখ্যার সাথে মিলে যায় তাই প্রতিটি বিযুক্ত এন-ডাইমেনশনাল ইনডেক্সিং সমস্যা হতে পারে মনো-মাত্রিক একটিতে হ্রাস পেয়েছে । এর অর্থ এই নয় যে এটি করার একমাত্র এবং একমাত্র উপায়: এটি "এটি সম্ভব" বলার উপায়। আপনার কেবলমাত্র একটি "বিভাজন এবং বিজয়" প্রক্রিয়া দরকার। ভার্চুয়াল ফাংশন হ'ল "ভাগ" এবং একাধিক উত্তরাধিকার হ'ল "বিজয়"।
এমিলিও গারাভাগলিয়া

... যখন সীমাবদ্ধ ক্ষেত্রের (সীমার) লিনিয়ার সংমিশ্রণের মধ্যে যা ঘটে তখন আরও কার্যকর হয় (ক্লাসিকাল i = r * C + c ম্যাট্রিক্সের ঘরের একটি অ্যারেতে সূচক পাওয়া যায়)। এই ক্ষেত্রে, ডিভাইড আইডিটি "দর্শনার্থী" এবং বিজয়ী হ'ল "সম্মিলিত"। যেহেতু লিনিয়ার বীজগণিত জড়িত, তাই এই ক্ষেত্রে কৌশলটি "তির্যক" এর সাথে মিলে যায়
এমিলিও গারাভাগলিয়া

এগুলি সকলকে কৌশল হিসাবে ভাবেন না। এগুলি কেবল উপমা
এমিলিও গারাভাগলিয়া

23

এটি একটি ছোট উদাহরণে একরকম ঝরঝরে দেখাচ্ছে, কিন্তু বাস্তব জীবনে আপনি শীঘ্রই এক ধরণের একে অপরকে পোঁকে দিতে পারে এমন একটি দীর্ঘ সেট নিয়ে শেষ করবেন, যার মধ্যে কয়েকটি সম্ভবত কেবল এক দিকেই।

কি সম্পর্কে dark_orange_node, বা black_and_orange_striped_node, বা dotted_node? এটি বিভিন্ন রঙের বিন্দু থাকতে পারে? যদি বেশিরভাগ বিন্দু কমলা হয় তবে কি তা খোঁচা দেওয়া যায়?

এবং প্রতিবার আপনাকে একটি নতুন নিয়ম যুক্ত করতে হবে, আপনাকে সমস্ত poke_adjacentফাংশনটি আবার দেখতে হবে এবং আরও বিবরণ যুক্ত করতে হবে।


সর্বদা হিসাবে, জেনেরিক উদাহরণগুলি তৈরি করা শক্ত, আমি আপনাকে এটি দেব give

তবে যদি আমি এই নির্দিষ্ট উদাহরণটি করি, আমি poke()সমস্ত ক্লাসে একজন সদস্য যুক্ত করব এবং তাদের কিছু void poke() {}আগ্রহী না হলে তাদের কল ( ) কলটি উপেক্ষা করতে দেব ।

অবশ্যই এটি typeids এর তুলনায় কম ব্যয়বহুল হবে ।


3
আপনি "অবশ্যই" বলছেন, তবে কী আপনাকে এতটা নিশ্চিত করে? এটিই আমি খুঁজে বের করার চেষ্টা করছি। ধরা যাক আমি কমলা_নোডের নাম পোকযোগ্য_নোডে রেখেছি, এবং তারাই কেবলমাত্র আমি কলকে কল করতে পারি ()। তার অর্থ হল যে আমার ইন্টারফেসটির জন্য একটি পোকে () পদ্ধতি প্রয়োগ করা দরকার যা বলে, একটি ব্যতিক্রম ছোঁড়ে ("এই নোডটি পোকযোগ্য নয়")। এটি আরও ব্যয়বহুল বলে মনে হচ্ছে ।
mbr0wn

2
কেন তাকে ব্যতিক্রম ছোঁড়াতে হবে? ইন্টারফেসটি "পোকে সক্ষম" কিনা তা যদি আপনি যত্নশীল হন তবে কেবল "ফস ফাংশন" যুক্ত করুন "এবং পোকার ফাংশনটি কল করার আগে প্রথমে কল করুন। অথবা কেবল তিনি যা বলেছিলেন তা করুন এবং "কিছু না করার জন্য, অ-পোকেবল ক্লাসে"।
ব্র্যান্ডন

1
@ এমবি0 ডব্লিউএন: আপনি কেন পোকেটেবল এবং ননপোকাবেবল নোড একই বেস ক্লাসে ভাগ করতে চান তা আরও ভাল প্রশ্ন।
নিকল বোলাস

2
@ নিকলবোলাস কেন আপনি বন্ধুত্বপূর্ণ এবং শত্রুতাবাদী দানবগুলি একই বেস শ্রেণি, বা ফোকাসেবল এবং অ-ফোকাসযোগ্য UI উপাদানগুলি, বা একটি নামপ্যাড ছাড়াই নামপ্যাড এবং কী-বোর্ড সহ কী-বোর্ড ভাগ করতে চান?
ব্যবহারকারী 253751

1
@ mbr0wn এটি আচরণ-নিদর্শন বলে মনে হচ্ছে। মৌলিক ইন্টারফেস দুটি পদ্ধতি রয়েছে supportsBehaviourএবং invokeBehaviourপ্রতিটি বর্গ আচরণে একটি তালিকা থাকতে পারে। একটি আচরণ হ'ল পোকে এবং পোকেযোগ্য হতে চায় এমন সমস্ত শ্রেণীর দ্বারা সমর্থিত আচরণের তালিকায় যুক্ত হতে পারে।
ফ্যালকো

20

কিছু সংকলক এটি ব্যবহার করে না / আরটিটিআই সর্বদা সক্ষম হয় না

আমি বিশ্বাস করি আপনি এই জাতীয় যুক্তি ভুল বুঝেছেন।

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

সমস্যা তাই লাইব্রেরি নিয়ে । এটি হ'ল আপনি যদি আরটিটিআই-র উপর নির্ভর করে একটি লাইব্রেরি লিখছেন তবে আপনার গ্রন্থাগারটি আরটিটিআই বন্ধ করে এমন ব্যবহারকারীরা ব্যবহার করতে পারবেন না । আপনি যদি চান যে আপনার লাইব্রেরিটি সেই লোকগুলির দ্বারা ব্যবহৃত হয়, তবে এটি আরটিটিআই ব্যবহার করতে পারে না, এমনকি যদি আপনার গ্রন্থাগারটিও আরটিটিআই ব্যবহার করতে পারে এমন লোকেরা ব্যবহার করে। একইভাবে গুরুত্বপূর্ণ, আপনি আরটিটিআই ব্যবহার করতে না পারলে আপনাকে গ্রন্থাগারগুলির জন্য আরও কিছুটা শক্ত কেনাকাটা করতে হবে, যেহেতু আরটিটিআই ব্যবহার আপনার জন্য একটি চুক্তি-ব্রেকার।

এটির জন্য অতিরিক্ত মেমরি খরচ হয় / ধীর হতে পারে

হট লুপগুলিতে আপনি না এমন অনেকগুলি জিনিস রয়েছে। আপনি মেমরি বরাদ্দ না। আপনি লিঙ্কযুক্ত তালিকার মাধ্যমে পুনরাবৃত্তি করবেন না। এবং তাই এগিয়ে। আরটিটিআই অবশ্যই "এখানে এটি করবেন না" জিনিসগুলির মধ্যে একটি হতে পারে।

তবে, আপনার সমস্ত আরটিটিআই উদাহরণ বিবেচনা করুন। সব ক্ষেত্রেই আপনার কাছে অনির্দিষ্টকালের একটি বা একাধিক অবজেক্ট রয়েছে এবং আপনি তাদের উপর কিছু অপারেশন করতে চান যা তাদের কারও পক্ষে সম্ভব নাও হতে পারে।

এটি এমন একটি জিনিস যা আপনার নকশায় কাজ করতে হবে পর্যায়ে । আপনি এমন পাত্রে লিখতে পারেন যা মেমরি বরাদ্দ করে না যা "এসটিএল" দৃষ্টান্তের সাথে খাপ খায়। আপনি লিঙ্কযুক্ত তালিকার ডেটা কাঠামো এড়াতে বা তাদের ব্যবহার সীমাবদ্ধ করতে পারেন। আপনি স্ট্রাইকগুলির অ্যারেগুলিকে অ্যারে বা যেকোনো কিছুতে স্ট্রাক্টগুলিতে পুনর্গঠিত করতে পারেন। এটি কিছু জিনিস পরিবর্তন করে তবে আপনি এটি বগিযুক্ত রাখতে পারেন।

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

তাহলে ... আপনি কেন এটি শুরু করার জন্য ভুল উপায়ে লিখেছিলেন?

আমাকে এমন বৈশিষ্ট্য বা পদ্ধতিগুলি সংজ্ঞায়িত করতে হবে না যেখানে আমার তাদের প্রয়োজন হয় না, বেস নোড শ্রেণিটি ঝুঁকিতে থাকতে পারে এবং বোঝাতে পারে।

কি শেষ?

আপনি বলছেন যে বেস ক্লাসটি "হাতা এবং গড়"। তবে সত্যই ... এটি অস্তিত্বহীন । এটি আসলে কিছু করে না ।

শুধু তোমার উদাহরণ তাকান: node_base। এটা কি? এটি এমন একটি জিনিস বলে মনে হচ্ছে যার সংলগ্ন অন্যান্য জিনিস রয়েছে। এটি একটি জাভা ইন্টারফেস (এটিতে পূর্ব-জেনারিক জাভা): এমন এক শ্রেণি যা ব্যবহারকারীদের আসল প্রকারে যেতে পারে এমন কিছু হতে পারে । সম্ভবত আপনি সংলগ্নতার মতো কিছু প্রাথমিক বৈশিষ্ট্য যুক্ত করেছেন (জাভা যোগ করে ToString), তবে এটি।

"পাতলা এবং গড়" এবং "স্বচ্ছ" এর মধ্যে পার্থক্য রয়েছে।

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

তবে তারা যা করে তা হ'ল বাস্তবে নতুন জিনিসগুলি করা এমনকি সিস্টেমের মধ্যেই এটি একটি বড় ব্যথা। আপনার poke_adjacent_orangesফাংশন বিবেচনা করুন । কেউ যদি এমন lime_nodeটাইপ চান যা কেবল orange_nodeএস এর মতো পোকার মতো করা যায় ? ঠিক আছে, আমরা lime_nodeথেকে প্রাপ্ত করতে পারি না orange_node; ওটা কোন অর্থ প্রকাশ করে না.

পরিবর্তে, আমাদের lime_nodeথেকে নেওয়া একটি নতুন যুক্ত করতে হবে node_base। তারপর নাম পরিবর্তন poke_adjacent_orangesকরতে poke_adjacent_pokables। এবং তারপরে, কাস্ট করার চেষ্টা করুন orange_nodeএবং lime_node; যা কিছু কাস্ট কাজ করে তা হল আমাদের po

তবে, lime_nodeএটি নিজস্ব নিজস্ব প্রয়োজন poke_adjacent_pokables । এবং এই ফাংশনটির জন্য একই কাস্টিং চেকগুলি করা দরকার।

এবং যদি আমরা একটি তৃতীয় প্রকার যুক্ত করি তবে আমাদের কেবল তার নিজস্ব ফাংশনটিই যুক্ত করতে হবে না, তবে অন্য দুটি শ্রেণিতে আমাদের অবশ্যই ফাংশনগুলি পরিবর্তন করতে হবে।

স্পষ্টতই, এখন আপনি poke_adjacent_pokablesএকটি নিখরচায় ফাংশন করেন, যাতে এটি তাদের সবার জন্য কাজ করে। তবে আপনি কি মনে করেন যে যদি কেউ চতুর্থ প্রকার যুক্ত করে এবং সেই ফাংশনটিতে এটি যুক্ত করতে ভুলে যায় তবে?

হ্যালো, নীরব বিচ্ছেদ । প্রোগ্রামটি কমবেশি ঠিকঠাকভাবে কাজ করছে বলে মনে হচ্ছে, তবে তা তা নয়। ছিল pokeএকটি করে প্রকৃত ভার্চুয়াল ফাংশন, কম্পাইলার যখন আপনার কাছ থেকে বিশুদ্ধ ভার্চুয়াল ফাংশন ওভাররাইড করা হয়নি ব্যর্থ হয়ে যেত node_base

আপনার উপায় সহ, আপনার কাছে এমন কোনও সংকলক চেক নেই। ওহ, নিশ্চিত যে সংকলকটি খাঁটি অমূল্য ভার্চুয়ালগুলির জন্য যাচাই করবে না, তবে কমপক্ষে আপনার সুরক্ষা থাকতে পারে যেখানে সুরক্ষা পাওয়া সম্ভব (যেমন: কোনও ডিফল্ট অপারেশন নেই)।

আরটিটিআই সহ স্বচ্ছ বেস ক্লাসগুলির ব্যবহার রক্ষণাবেক্ষণের দুঃস্বপ্নের দিকে নিয়ে যায়। প্রকৃতপক্ষে, আরটিটিআই-র বেশিরভাগ ব্যবহার রক্ষণাবেক্ষণের মাথা ব্যাথার দিকে নিয়ে যায়। তার মানে এই নয় যে RTTI নয় দরকারী (এটা তৈরীর জন্য অত্যাবশ্যক boost::anyকাজ উদাহরণস্বরূপ)। তবে এটি অত্যন্ত বিশেষায়িত প্রয়োজনগুলির জন্য একটি খুব বিশেষ সরঞ্জাম ।

এইভাবে, এটি একইভাবে "ক্ষতিকারক" goto। এটি একটি দরকারী সরঞ্জাম যা দিয়ে শেষ করা উচিত নয়। তবে এটি আপনার কোডের মধ্যে ব্যবহার বিরল হওয়া উচিত ।


সুতরাং, যদি আপনি স্বচ্ছ বেস ক্লাস এবং গতিশীল ingালাই ব্যবহার করতে না পারেন তবে কীভাবে আপনি চর্বিযুক্ত ইন্টারফেসগুলি এড়াতে পারবেন? বেস ক্লাসে বুদবুদ থেকে শুরু করে কোনও ধরণের ফোন করতে আপনি যে ফাংশনটি কল করতে চাইতে পারেন তা কীভাবে বাঁচবেন?

উত্তর বেস শ্রেণীর জন্য কি উপর নির্ভর করে।

স্বচ্ছ বেস ক্লাসগুলি node_baseকেবল সমস্যার জন্য ভুল সরঞ্জামটি ব্যবহার করছে। লিঙ্কযুক্ত তালিকাগুলি দ্বারা সেরা পরিচালনা করা হয়। নোড টাইপ এবং সংলগ্নতা একটি টেম্পলেট ধরণের দ্বারা সরবরাহ করা হবে। আপনি যদি তালিকায় একটি পলিমারফিক টাইপ রাখতে চান তবে পারেন। টেমপ্লেট যুক্তি BaseClass*হিসাবে কেবল ব্যবহার করুন T। অথবা আপনার পছন্দসই স্মার্ট পয়েন্টার।

তবে অন্যান্য পরিস্থিতিতে আছে। একটি হ'ল এক প্রকার যা প্রচুর কাজ করে তবে এর কিছু alচ্ছিক অংশ রয়েছে। একটি নির্দিষ্ট উদাহরণ নির্দিষ্ট ফাংশন প্রয়োগ করতে পারে, অন্যটি না করে। যাইহোক, এই জাতীয় ধরণের নকশা সাধারণত একটি সঠিক উত্তর দেয়।

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

এর জন্য আধুনিক সমাধান একটি উপাদান উপাদান পদ্ধতি। Entityএটি কেবলমাত্র উপাদানগুলির একটি সেটের ধারক, যার মধ্যে কিছু আঠালো থাকে। কিছু উপাদান alচ্ছিক; কোনও সত্তার ভিজ্যুয়াল প্রতিনিধিত্ব নেই তার "গ্রাফিক্স" উপাদান নেই। এআই নয় এমন সত্তার কোনও "নিয়ামক" উপাদান নেই। এবং তাই এগিয়ে।

এই জাতীয় সিস্টেমে সত্তা উপাদানগুলির জন্য কেবল পয়েন্টার হয়, তাদের ইন্টারফেসের বেশিরভাগ অংশগুলি সরাসরি উপাদানগুলিতে অ্যাক্সেসের মাধ্যমে সরবরাহ করা হয়।

এই জাতীয় উপাদান বিকাশের জন্য নকশার পর্যায়ে স্বীকৃতি প্রয়োজন যে নির্দিষ্ট ফাংশনগুলি একত্রে একত্রে গোষ্ঠীযুক্ত, যেমন যে সমস্ত প্রকার যা প্রয়োগ করে সেগুলি সেগুলি বাস্তবায়ন করে। এটি আপনাকে সম্ভাব্য বেস ক্লাস থেকে ক্লাসটি বের করতে এবং এটিকে একটি পৃথক উপাদান তৈরি করতে দেয়।

এটি একক দায়িত্বের নীতি অনুসরণ করতে সহায়তা করে। এই জাতীয় সংযুক্ত শ্রেণীর কেবল উপাদানগুলির ধারক হওয়ার দায়িত্ব রয়েছে।


ম্যাথু ওয়ালটন থেকে:

আমি লক্ষ করেছি যে প্রচুর উত্তরের ধারণাটি নোট করে না যে আপনার উদাহরণটি নোড_বেসটি একটি লাইব্রেরির অংশ এবং ব্যবহারকারীরা তাদের নিজস্ব নোড প্রকার তৈরি করবে। তারপরে তারা অন্য সমাধানের মঞ্জুরি দেওয়ার জন্য নোড_বেস সংশোধন করতে পারবেন না, তাই সম্ভবত আরটিটিআই তখন তাদের সেরা বিকল্প হয়ে উঠবে।

ঠিক আছে, আসুন এটি অন্বেষণ করা যাক।

এটি বোঝার জন্য, আপনার কাছে যা থাকতে হবে তা হ'ল কিছু লাইব্রেরি এল একটি ধারক বা ডেটা কাঠামোগত ধারক সরবরাহ করে। ব্যবহারকারী এই ধারকটিতে ডেটা যুক্ত করতে পারে, এর বিষয়বস্তুগুলি ইত্যাদির উপর পুনরাবৃত্তি করে তবে লাইব্রেরিটি এই ডেটা দিয়ে সত্যই কিছু করে না; এটি কেবল তার অস্তিত্ব পরিচালনা করে।

এটি এমনকি তার অস্তিত্বকে এতটা ধ্বংস হিসাবে পরিচালনা করে না । কারণটি হ'ল, যদি আপনি এই জাতীয় উদ্দেশ্যে আরটিটিআই ব্যবহার করার প্রত্যাশা করেন তবে আপনি এমন ক্লাস তৈরি করছেন যা এল অবজ্ঞ। এর অর্থ আপনার কোড অবজেক্ট বরাদ্দ করে এবং পরিচালনার জন্য এটি এল এর হাতে দেয়।

এখন, এমন কিছু ঘটনা রয়েছে যেখানে এরকম কিছু বৈধ নকশা design ইভেন্ট সিগন্যালিং / বার্তা পাসিং, থ্রেড-নিরাপদ কাজের সারি ইত্যাদি pattern ।

সি-তে, এই প্যাটার্নটি বানানযুক্ত void*, এবং এটির ব্যবহারটি ভাঙা এড়াতে অনেক যত্নের প্রয়োজন। সি ++ এ, এই প্যাটার্নটি বানান std::experimental::any(শীঘ্রই বানান হবে std::any)।

যেভাবে এটি কাজ করা উচিত তা হ'ল এল এমন একটি node_baseশ্রেণীর সরবরাহ করে যা anyআপনার প্রকৃত ডেটার প্রতিনিধিত্ব করে takes আপনি যখন বার্তাটি পাবেন, থ্রেড ক্যু কাজের আইটেম, বা আপনি যা কিছু করছেন তখন আপনি এটি anyতার যথাযথ প্রকারে ফেলে দেন , যা প্রেরক এবং গ্রহণকারী উভয়ই জানেন।

সুতরাং orange_nodeথেকে প্রাপ্ত করার পরিবর্তে node_data, আপনি কেবলমাত্র এর সদস্য ক্ষেত্রের orangeঅভ্যন্তরে আটকে থাকুন । শেষ ব্যবহারকারী এটি এক্সট্রাক্ট করে এবং এতে রূপান্তর করতে ব্যবহার করে । যদি কাস্ট ব্যর্থ হয় তবে তা হয়নি ।node_dataanyany_castorangeorange

এখন, আপনি যদি প্রয়োগের সাথে কিছুটা পরিচিত হন any, আপনি সম্ভবত বলবেন, "আরে এক মিনিট অপেক্ষা করুন: any অভ্যন্তরীণভাবে আরটিটিআই ব্যবহার করতে হবেany_cast কাজ ।" আমি এর উত্তর, "... হ্যাঁ"।

এটি একটি বিমূর্ততা বিন্দু । বিশদটি গভীরভাবে বিবেচনা করুন, কেউ আরটিটিআই ব্যবহার করছেন। তবে যে স্তরে আপনার পরিচালনা করা উচিত, সরাসরি আরটিটিআই এমন কিছু নয় যা আপনার করা উচিত।

আপনার পছন্দসই কার্যকারিতা সরবরাহ করার জন্য আপনাকে এমন ধরণের ব্যবহার করা উচিত। সর্বোপরি, আপনি আরটিটিআই চান না। আপনি যা চান তা হ'ল একটি ডেটা স্ট্রাকচার যা প্রদত্ত প্রকারের মান সংরক্ষণ করতে পারে, এটিকে পছন্দসই গন্তব্য ব্যতীত সকলের কাছ থেকে আড়াল করতে পারে, তারপরে যাচাই করা হয় যে সঞ্চিত মানটি সেই ধরণের back

বলা হয় any। এটা তোলে ব্যবহার RTTI কিন্তু ব্যবহার anyকরার কারণে এটিকে আকাঙ্ক্ষিত শব্দার্থবিদ্যা সঠিকভাবে ফিট করে, এ পর্যন্ত RTTI সরাসরি ব্যবহার শ্রেয়।


10

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

যখন আপনি আরটিটিআই ব্যবহার করেন কোনও নির্দিষ্ট কাজ করতে পারে এমন বিশেষ অবজেক্টগুলির একটি প্রাক-নির্বাচন করার জন্য, যখন একই সংস্থার অন্যরা পারেন না, আপনি বিশ্বের সেই আরামদায়ক দৃষ্টিভঙ্গি ভঙ্গ করছেন। হঠাৎ এই কলারের কাছে তার মিনিনদের কেবল এটি চালিয়ে যেতে বলার পরিবর্তে কে কী করতে পারে তা জানতে হবে to কিছু লোক এতে বিরক্ত, এবং আমার সন্দেহ হয় যে এটি আরটিটিআইকে কিছুটা নোংরা বলে মনে করা হয় তার একটি বড় অংশ।

কোন পারফরম্যান্স সমস্যা আছে? সম্ভবত, তবে আমি এটি কখনও অনুভব করি নি, এবং এটি কুড়ি বছর আগে থেকে, বা এমন লোকদের কাছ থেকে যারা প্রৌ believe়ভাবে বিশ্বাস করে যে দুটিয়ের পরিবর্তে তিনটি সংসদীয় নির্দেশাবলী ব্যবহার করা গ্রহণযোগ্য নয় at

সুতরাং কীভাবে এটি মোকাবেলা করবেন ... আপনার অবস্থার উপর নির্ভর করে কোনও নোড-নির্দিষ্ট বৈশিষ্ট্য পৃথক বস্তুগুলিতে বান্ডিল করা অর্থপূর্ণ হতে পারে (অর্থাত্ পুরো 'কমলা' এপিআই পৃথক বস্তু হতে পারে)। রুট অবজেক্টটির পরে 'কমলা' এপিআই ফিরে আসার জন্য ভার্চুয়াল ফাংশন থাকতে পারে, নন-অরেঞ্জ বস্তুগুলির জন্য ডিফল্টরূপে নালপ্ট্রার ফিরিয়ে দেওয়া হবে।

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


6
পুনরায়: পারফরম্যান্সের ব্যয় - আমি 3 গিগাহার্টজ প্রসেসরে আমাদের অ্যাপ্লিকেশনে প্রায় 2µs ব্যয় হিসাবে ডায়নামিক_কাস্ট <> পরিমাপ করেছি, যা এনাম পরীক্ষা করার চেয়ে 1000x কম ধীর। (আমাদের অ্যাপ্লিকেশনটিতে একটি 11.1 মিমি মূল লুপের শেষ সময়সীমা রয়েছে, তাই আমরা মাইক্রোসেকেন্ডগুলি সম্পর্কে অনেক
যত্নশীল

6
সম্পাদনা বাস্তবায়নের মধ্যে পার্থক্য অনেক বেশি। জিসিসি একটি টাইপফর্ম পয়েন্টার তুলনা ব্যবহার করে যা দ্রুত। এমএসভিসি স্ট্রিং তুলনাগুলি ব্যবহার করে যা দ্রুত নয়। তবে এমএসভিসির পদ্ধতিটি লাইব্রেরি, স্ট্যাটিক বা ডিএলএল-র বিভিন্ন সংস্করণের সাথে সংযুক্ত কোডের সাথে কাজ করবে, যেখানে জিসিসির পয়েন্টার পদ্ধতিটি বিশ্বাস করে যে স্ট্যাটিক লাইব্রেরির একটি শ্রেণি একটি ভাগ করা লাইব্রেরির শ্রেণীর চেয়ে আলাদা।
জ্যান লিংস

1
@ ক্র্যাশওয়ার্কস এখানে কেবল একটি সম্পূর্ণ রেকর্ড আছে: কোন সংকলক (এবং কোন সংস্করণ) ছিল?
এইচ। গুইজট

@ ক্র্যাশওয়ার্কস তথ্যের জন্য অনুরোধটির পিছনে রয়েছে যা সংকলক আপনার পর্যবেক্ষণের ফলাফলগুলি তৈরি করেছে; ধন্যবাদ।
আন্ডারস্কোর_

@ফোনস্কোর_ডি: এমএসভিসি।
ক্রাশ ওয়ার্কস 21

9

সি ++ স্ট্যাটিক টাইপ চেকিংয়ের আইডিয়াতে নির্মিত।

[1] RTTI, যে, dynamic_castএবং type_id, ডায়নামিক টাইপ পরীক্ষণ হয়।

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


পুনরায়

আমি টেমপ্লেট বা অন্যান্য পদ্ধতিতে এটি করার কোনও পরিষ্কার উপায় জানতাম না

আপনি এই প্রক্রিয়াটি হেটেরোজেনাস নোডস-অফ-অ-গ্রাফ স্থিতিশীল প্রকারের চেকিং এবং দর্শকের প্যাটার্নের মাধ্যমে কোনও কাস্টিংয়ের মাধ্যমে করতে পারেন, যেমন:

#include <iostream>
#include <set>
#include <initializer_list>

namespace graph {
    using std::set;

    class Red_thing;
    class Yellow_thing;
    class Orange_thing;

    struct Callback
    {
        virtual void handle( Red_thing& ) {}
        virtual void handle( Yellow_thing& ) {}
        virtual void handle( Orange_thing& ) {}
    };

    class Node
    {
    private:
        set<Node*> connected_;

    public:
        virtual void call( Callback& cb ) = 0;

        void connect_to( Node* p_other )
        {
            connected_.insert( p_other );
        }

        void call_on_connected( Callback& cb )
        {
            for( auto const p : connected_ ) { p->call( cb ); }
        }

        virtual ~Node(){}
    };

    class Red_thing
        : public virtual Node
    {
    public:
        void call( Callback& cb ) override { cb.handle( *this ); }

        auto redness() -> int { return 255; }
    };

    class Yellow_thing
        : public virtual Node
    {
    public:
        void call( Callback& cb ) override { cb.handle( *this ); }
    };

    class Orange_thing
        : public Red_thing
        , public Yellow_thing
    {
    public:
        void call( Callback& cb ) override { cb.handle( *this ); }

        void poke() { std::cout << "Poked!\n"; }

        void poke_connected_orange_things()
        {
            struct Poker: Callback
            {
                void handle( Orange_thing& obj ) override
                {
                    obj.poke();
                }
            } poker;

            call_on_connected( poker );
        }
    };
}  // namespace graph

auto main() -> int
{
    using namespace graph;

    Red_thing   r;
    Yellow_thing    y1, y2;
    Orange_thing    o1, o2, o3;

    for( Node* p : std::initializer_list<Node*>{ &y1, &y2, &r, &o2, &o3 } )
    {
        o1.connect_to( p );
    }
    o1.poke_connected_orange_things();
}

এটি ধরে নেওয়া হয় যে নোড প্রকারের সেটটি পরিচিত।

যখন এটি না হয়, দর্শকের প্যাটার্ন (এটির অনেকগুলি প্রকরণ রয়েছে) কয়েকটি কেন্দ্রীয়ীকৃত বর্ণ, বা কেবল একটি একক দিয়ে প্রকাশ করা যেতে পারে।


একটি টেমপ্লেট-ভিত্তিক পদ্ধতির জন্য বুস্ট গ্রাফ লাইব্রেরি দেখুন। দুঃখের সাথে বলতে হয় যে আমি এর সাথে পরিচিত নই, আমি এটি ব্যবহার করি নি। সুতরাং আমি নিশ্চিত না যে এটি কী করে এবং কীভাবে এবং কোন ডিগ্রিতে এটি আরটিটিআইয়ের পরিবর্তে স্থির ধরণের চেকিং ব্যবহার করে, তবে যেহেতু বুস্ট সাধারনত কেন্দ্রীয় ধারণা হিসাবে স্ট্যাটিক টাইপ পরীক্ষার সাথে টেম্পলেট-ভিত্তিক হয়, তাই আমি মনে করি আপনি এটি খুঁজে পাবেন এর গ্রাফ সাব-লাইব্রেরিটি স্ট্যাটিক ধরণের পরীক্ষার উপর ভিত্তি করে is


[1] রান টাইম তথ্য


1
একটি "মজার বিষয়" লক্ষণীয় যে ভিজিটর প্যাটার্নের জন্য প্রয়োজনীয় কোডের পরিমাণ হ্রাস করতে পারে (প্রকারগুলি যুক্ত করার সময় পরিবর্তনগুলি) আরটিটিআই ব্যবহার করে একটি শ্রেণিবিন্যাসকে "আরোহণ" করতে হয়। আমি এটি "অ্যাসাইক্লিক ভিজিটর ধরণ" হিসাবে জানি।
ড্যানিয়েল জোর

3

অবশ্যই এমন একটি দৃশ্য আছে যেখানে পলিমারফিজম সাহায্য করতে পারে না: নামগুলি। typeidএই নামটি যেভাবে এনকোড করা হয়েছে তা বাস্তবায়ন-সংজ্ঞায়িত হলেও আপনাকে প্রকারের নাম অ্যাক্সেস করতে দেয়। আপনি সাধারণত দ্বিগুণ তুলনা করতে পারেন তবে সাধারণত এটি কোনও সমস্যা নয় typeid:

if ( typeid(5) == "int" )
    // may be false

if ( typeid(5) == typeid(int) )
   // always true

একই hashes জন্য হোল্ড।

[...] আরটিটিআই কে "ক্ষতিকারক" হিসাবে বিবেচনা করা হয়

ক্ষতিকর স্পষ্টভাবে বাড়িয়ে হল: RTTI কিছু অপূর্ণতা আছে, কিন্তু এটা করে সুফল খুব আছে।

আপনাকে আরটিটিআই ব্যবহার করতে হবে না। আরটিটিআই হ'ল ওওপি সমস্যাগুলি সমাধান করার একটি সরঞ্জাম : আপনি যদি অন্য কোনও দৃষ্টান্ত ব্যবহার করেন তবে এগুলি সম্ভবত অদৃশ্য হয়ে যাবে। সিতে আরটিটিআই নেই, তবে এখনও কাজ করে। সি ++ পরিবর্তে সম্পূর্ণরূপে গলি সমর্থন করে এবং আপনি দেয় একাধিক সরঞ্জাম কিছু সমস্যাটি হল এই যে রানটাইম তথ্য প্রয়োজন হতে পারে পরাস্ত: তাদের মধ্যে একজন হল প্রকৃতপক্ষে RTTI, যা যদিও মূল্য দিয়ে আসে। আপনি যদি এটির সামর্থ্য না রাখেন তবে নিরাপদ পারফরম্যান্স বিশ্লেষণের পরে আপনি কেবল আরও ভাল অবস্থা করতে চান, এখনও পুরানো স্কুল রয়েছে void*: এটি বিনামূল্যে। নিখরচার। তবে আপনি কোনও ধরণের সুরক্ষা পাবেন না। সুতরাং এটি সব ব্যবসা সম্পর্কে।


  • কিছু সংকলক ব্যবহার করেন না / আরটিটিআই সর্বদা সক্ষম হয় না
    আমি সত্যিই এই যুক্তিটি কিনি না। এটি বলার মতো যে আমার সি ++ 14 বৈশিষ্ট্যগুলি ব্যবহার করা উচিত নয়, কারণ সেখানে এমন সংকলক রয়েছে যা এটি সমর্থন করে না। এবং তবুও, কেউ আমাকে সি ++ 14 বৈশিষ্ট্য ব্যবহার থেকে নিরুৎসাহিত করবে না।

আপনি যদি সি ++ কোড অনুসারে (সম্ভবত কঠোরভাবে) লিখেন তবে বাস্তবায়ন নির্বিশেষে আপনি একই আচরণ আশা করতে পারেন। স্ট্যান্ডার্ড-কমপ্লায়েন্ট বাস্তবায়নগুলি স্ট্যান্ডার্ড সি ++ বৈশিষ্ট্যগুলিকে সমর্থন করবে।

তবে বিবেচনা করুন যে কিছু পরিবেশে সি ++ সংজ্ঞায়িত («ফ্রিস্ট্যান্ডিং» বেশী), আরটিটিআই সরবরাহ করার দরকার নেই এবং এর ব্যতিক্রমও নেই, virtualইত্যাদি। আরটিটিআইয়ের সঠিকভাবে কাজ করার জন্য একটি অন্তর্নিহিত স্তর প্রয়োজন যা এবিআই এবং প্রকৃত ধরণের তথ্যের মতো নিম্ন-স্তরের বিশদগুলি সরবরাহ করে।


আমি এক্ষেত্রে আরটিটিআই সম্পর্কিত ইয়াককের সাথে একমত। হ্যাঁ, এটি ব্যবহার করা যেতে পারে; তবে এটি কি যৌক্তিকভাবে সঠিক? যে ভাষা আপনাকে এই চেকটিকে বাইপাস করতে দেয় তার অর্থ এই নয় যে এটি করা উচিত।

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