সি ++ এ, ভার্চুয়াল পদ্ধতি ঘোষণায় কখন চূড়ান্ত ব্যবহার করব?


11

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

আমার প্রশ্নটি পরবর্তী:

কোন দরকারী ক্ষেত্রে যখন আমি সত্যিই ব্যবহার করা উচিত হয় finalমধ্যে virtualপদ্ধতি ঘোষণা?


সমস্ত একই কারণে জাভা পদ্ধতিগুলি চূড়ান্ত করা হয়?
14

জাভাতে সমস্ত পদ্ধতি ভার্চুয়াল। বেস শ্রেণিতে চূড়ান্ত পদ্ধতি পারফরম্যান্সকে উন্নত করতে পারে। সি ++ এর অ-ভার্চুয়াল পদ্ধতি রয়েছে, সুতরাং এটি এই ভাষার ক্ষেত্রে নয়। আপনি অন্য কোন ভাল কেস জানেন? আমি তাদের শুনতে চাই। :)
metamaker

অনুমান করুন আমি বিষয়গুলি ব্যাখ্যা করতে খুব ভাল নই - আমি মাইক নাকিসের মতো ঠিক একই জিনিসটি বলার চেষ্টা করছিলাম।
Ordous

উত্তর:


12

finalকীওয়ার্ডটি কী করে তার একটি পুনরুদ্ধার : আসুন আমরা বলি যে আমাদের কাছে বেস ক্লাস Aএবং উত্পন্ন ক্লাস রয়েছে B। ফাংশন হিসাবে হিসাবে f()ঘোষিত হতে পারে , যার অর্থ শ্রেণি এটি ওভাররাইড করে। তবে ক্লাসটি আশা করতে পারে যে আরও যে ক্লাস থেকে আরও উত্পন্ন হয়েছে সেগুলি ওভাররাইড করতে সক্ষম না হবে । যে যখন আমরা ঘোষণা করতে প্রয়োজন হিসাবে মধ্যে । কীওয়ার্ড ব্যতীত একবার আমরা কোনও পদ্ধতিটিকে ভার্চুয়াল হিসাবে সংজ্ঞায়িত করি, যে কোনও উদ্ভূত শ্রেণি এটিকে ওভাররাইড করতে পারে। শব্দ এই স্বাধীনতা শেষ করা করতে ব্যবহৃত হয়।AvirtualBBBf()f()finalBfinalfinal

কেন তুমি এমন কথা হবে এর একটি উদাহরণ: ধরুন বর্গ Aএকটি ভার্চুয়াল ফাংশন নির্ধারণ prepareEnvelope()এবং ক্লাস Bএটা ওভাররাইড এবং এটি কার্যকরী নিজস্ব ভার্চুয়াল পদ্ধতি কল একটি ক্রম হিসাবে stuffEnvelope(), lickEnvelope()এবং sealEnvelope()। শ্রেণি Bউদ্ভূত শ্রেণিকে এই বাস্তব ভার্চুয়াল পদ্ধতিগুলিকে তাদের নিজস্ব বাস্তবায়ন সরবরাহ Bকরার জন্য মঞ্জুরি দেয় , কিন্তু শ্রেণি কোনও উদ্ভূত শ্রেণিকে ওভাররাইড করার অনুমতি দেয় না prepareEnvelope()এবং এভাবে স্টাফের ক্রম, লেট, সীল, বা এর মধ্যে কোনওটি বাদ দিতে ছাড়তে চায় না। সুতরাং, Bএক্ষেত্রে শ্রেণি prepareEnvelope()চূড়ান্ত হিসাবে ঘোষণা করে ।


প্রথম, উত্তরের জন্য আপনাকে ধন্যবাদ তবে আমার প্রশ্নের প্রথম বাক্যে আমি যা লিখেছি তা হুবহু নয়? আমার আসলে যা দরকার তা কেস কখন class B might wish that any class which is further derived from B should not be able to override f()? বিশ্বব্যাপী এমন কি এমন কোনও ঘটনা রয়েছে যেখানে এই ধরণের শ্রেণি বি এবং পদ্ধতি এফ () উপস্থিত থাকে এবং ভাল ফিট করে?
রূপান্তরকারী

হ্যাঁ, আমি দুঃখিত, স্থির থাকুন, আমি এখনই একটি উদাহরণ লিখছি।
মাইক নাকিস

@ মিটামেকার আপনি সেখানে যান
মাইক নাকিস

1
সত্যিই ভাল উদাহরণ, এটি এখন পর্যন্ত সেরা উত্তর। ধন্যবাদ!
metamaker

1
তারপরে নষ্ট সময়ের জন্য ধন্যবাদ আমি ইন্টারনেটে একটি ভাল উদাহরণ খুঁজে পাইনি, অনুসন্ধানে অনেক সময় নষ্ট করলাম। আমি উত্তরের জন্য +1 রাখব তবে আমার সুনাম কম থাকায় আমি এটি করতে পারছি না। :( হয়তো পরে।
metamaker

2

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

উদাহরণ

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

class Vehicle
{
public:
    virtual ~Vehicle {}

    bool transport(const Location& location)
    {
        // Mandatory check performed for all vehicle types. We could potentially
        // throw or assert here instead of returning true/false depending on the
        // exceptional level of the behavior (whether it is a truly exceptional
        // control flow resulting from external input errors or whether it's
        // simply a bug for the assert approach).
        if (valid_location(location))
            return travel_to(location);

        // If the location is not valid, no vehicle type can go there.
        return false;
    }

private:
    // Overridden by vehicle types. Note that private access here
    // does not prevent derived, nonfriends from being able to override
    // this function.
    virtual bool travel_to(const Location& location) = 0;
};

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

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

class FlyingVehicle: public Vehicle
{
private:
    bool travel_to(const Location& location) final
    {
        // Mandatory check performed for all flying vehicle types.
        if (safety_inspection())
            return fly_to(location);

        // If the safety inspection fails for a flying vehicle, 
        // it will not be allowed to fly to the location.
        return false;
    }

    // Overridden by flying vehicle types.
    virtual void safety_inspection() const = 0;
    virtual void fly_to(const Location& location) = 0;
};

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

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

যেখানে এটা finalএকটি নকশা / স্থাপত্য দৃষ্টিকোণ থেকে দরকারী।

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

প্রশ্ন

মন্তব্য থেকে:

চূড়ান্ত এবং ভার্চুয়াল কেন একই সময়ে ব্যবহৃত হবে?

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

struct Foo
{
   virtual ~Foo() {}
   virtual void f() = 0;
};

struct Bar: Foo
{
   /*implicitly virtual*/ void f() final {...}
};

এই ক্ষেত্রে, Bar::fস্পষ্টভাবে ভার্চুয়াল কীওয়ার্ডটি ব্যবহার করুন বা না করুন , Bar::fএটি একটি ভার্চুয়াল ফাংশন। virtualকীওয়ার্ডটি তখন এক্ষেত্রে becomesচ্ছিক হয়। সুতরাং এটি ভার্চুয়াল ফাংশন হয়ে থাকলেও ( কেবল ভার্চুয়াল ফাংশনগুলির জন্যই ব্যবহার করা যেতে পারে) এটি Bar::fনির্দিষ্ট করার জন্য এটি বোধগম্য হতে পারে ।finalfinal

এবং কিছু লোক স্পাইলালিস্টিকভাবে স্পষ্টভাবে নির্দেশ করতে পারে যে Bar::fভার্চুয়াল, যেমন:

struct Bar: Foo
{
   virtual void f() final {...}
};

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


আপনি কীভাবে privateআপনার Vehicleক্লাসের ভিতরে থাকা পদ্ধতিটিকে ওভাররাইড করার পরিকল্পনা করছেন ? আপনি protectedপরিবর্তে না মানে ?
অ্যান্ডি

3
@ ডেভিডপ্যাকার privateওভাররাইডিং (কিছুটা বিস্মৃত -স্বজ্ঞাত) প্রসারিত করে না। ভার্চুয়াল ফাংশনগুলির জন্য সর্বজনীন / সুরক্ষিত / প্রাইভেট স্পেসিফায়ার কেবল কলারদের জন্যই প্রয়োগ হয় এবং ওভাররাইডারগুলিতে অপরিশোধিতভাবে রাখে না। একটি উত্পন্ন শ্রেণি তার দৃশ্যমানতা নির্বিশেষে এর বেস বর্গ থেকে ভার্চুয়াল ফাংশনগুলিকে ওভাররাইড করতে পারে।

@ ডেভিডপ্যাকার protectedহয়ত কিছুটা স্বজ্ঞাত বোধ করতে পারে। আমি যখনই পারি কেবল সর্বনিম্ন-দৃশ্যমানতার জন্য পৌঁছতে পছন্দ করি। আমি মনে করি যে ভাষাটি এইভাবে ডিজাইন করা হয়েছে তা হ'ল, অন্যথায়, ব্যক্তিগত ভার্চুয়াল সদস্য ফাংশনগুলি বন্ধুত্বের প্রেক্ষাপটের বাইরে যা কিছু বোঝায় না, যেহেতু প্রচ্ছদে অ্যাক্সেস স্পেসিফায়ারগুলি বিবেচ্য থাকলে কোনও শ্রেণি ব্যতীত কোনও বন্ধু সেগুলি ওভাররাইড করতে সক্ষম হবে না ওভাররাইডিং এবং কেবল কলিং নয় of

আমি ভেবেছিলাম এটি ব্যক্তিগত হিসাবে সেট করাও সংকলন করবে না। উদাহরণস্বরূপ জাভা বা সি # উভয়ই এটির অনুমতি দেয় না। সি ++ আমাকে প্রতিদিন অবাক করে। এমনকি 10 বছর পর প্রোগ্রামিং।
অ্যান্ডি

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

0
  1. এটি প্রচুর অপটিমাইজেশন সক্ষম করে, কারণ এটি সংকলন সময়ে জানা যাবে কোন ফাংশনটি বলা হয়।

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


কেন finalএবং virtualকখনও একই সাথে ব্যবহার করা হবে?
রবার্ট হার্ভে

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

পুনঃটুইট অন্য যে কোনও ক্ষেত্রে এটি সম্ভবত হওয়া উচিত finalএবং override
উত্সাহক

@ মেটামেকার আমার এখানে একই প্রশ্ন ছিল, এখানে মন্তব্যে আলোচিত - প্রোগ্রামার্স.স্ট্যাকেক্সেঞ্জার / কুইকশানস / 256778/… - এবং মজার মজার কারণে কেবল আরও জিজ্ঞাসা করেই অন্য বেশ কয়েকটি আলোচনায় হোঁচট খেয়েছে! মূলত, এটি কোনও অপ্টিমাইজ করা সংকলক / লিঙ্কার নির্ধারণ করতে পারে যে কোনও রেফারেন্স / পয়েন্টার কোনও উদ্ভূত শ্রেণীর প্রতিনিধিত্ব করতে পারে এবং সুতরাং ভার্চুয়াল কল প্রয়োজন। যদি পদ্ধতিটি (বা শ্রেণি) যথাযথভাবে রেফারেন্সের নিজস্ব স্থিতিশীল প্রকারের বাইরে ওভাররাইড করা না যায়, তবে তারা ডেভर्चুয়ালাইজ করতে পারে: সরাসরি কল করুন। যদি কোনও সন্দেহ থাকে - তবে প্রায়শই - তাদের অবশ্যই কার্যত কল করতে হবে। ঘোষণা finalতাদের সত্যই সহায়তা করতে পারে
আন্ডারস্কোর_ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.