সি ++ এ ব্যক্তিগত ভার্চুয়াল পদ্ধতি


125

সি ++ এ কোনও প্রাইভেট পদ্ধতি ভার্চুয়াল করার সুবিধা কী?

আমি এটি একটি মুক্ত উত্স সি ++ প্রকল্পে লক্ষ্য করেছি:

class HTMLDocument : public Document, public CachedResourceClient {
private:
    virtual bool childAllowed(Node*);
    virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&);
};

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

1
@ শ্রীভাতসার আর তবে আপনি নিজের প্রশ্নের উত্তরও দেননি ......
স্পেনসার

@ শ্রীভৎসরআর আমি ভেবেছিলাম আপনার পেছনের দিকটি অন্যভাবে বোঝানো উচিত: ভার্চুয়াল পদ্ধতিটি ব্যক্তিগত না করে কী লাভ ?
পিটার - মনিকা পুনরায়

উত্তর:


116

ঔষধি Sutter খুব সুন্দরভাবে স্পষ্ট করে বলা হয়েছে এখানে

গাইডলাইন # 2: ভার্চুয়াল ফাংশনগুলিকে ব্যক্তিগত করতে পছন্দ করুন।

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


আপনি যেমন আমার উত্তরটি অনুমান করতে পারেন, আমি মনে করি সুতারের নির্দেশিকা # 3 বরং উইন্ডোটির বাইরে গাইডলাইন # 2 সরিয়েছে।
স্প্যান্সার

66

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

(তার উত্তরে প্রসূন সৌরভের উদ্ধৃত হার্ব সুটারের বিরোধিতা করে, সি ++ এফএকিউ লাইট বেসরকারী ভার্চুয়ালদের বিরুদ্ধে প্রস্তাব দেয় , বেশিরভাগ কারণেই এটি প্রায়শই মানুষকে বিভ্রান্ত করে)


41
দেখা যাচ্ছে যে সি ++ এফএকিউ লাইট তার সুপারিশটি পরিবর্তিত করেছে: " সি ++ এফএকিউ পূর্বে ব্যক্তিগত ভার্চুয়ালগুলির চেয়ে সুরক্ষিত ভার্চুয়ালগুলি ব্যবহার করার পরামর্শ দেওয়া হয়েছিল। তবে ব্যক্তিগত ভার্চুয়াল পদ্ধতিটি এখন যথেষ্ট সাধারণ যে নবীনীদের বিভ্রান্তি কম উদ্বেগের বিষয় নয়। "
জ্যাক মানব

19
বিশেষজ্ঞদের বিভ্রান্তি অবশ্য উদ্বেগের বিষয় remains আমার পাশে বসে থাকা চার সি ++ পেশাদারদের মধ্যে কেউই ব্যক্তিগত ভার্চুয়াল সম্পর্কে সচেতন ছিলেন না।
নিউটনেক্স

12

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

class Base
{
 private:

 int m_data;

 virtual void cleanup() { /*do something*/ }

 protected:
 Base(int idata): m_data (idata) {}

 public:

 int data() const { return m_data; }
 void set_data (int ndata) { m_data = ndata; cleanup(); }
};

class Derived: public Base
{
 private:
 void cleanup() override
 {
  // do other stuff
  Base::cleanup(); // nope, can't do it
 }
 public:
 Derived (int idata): base(idata) {}
};

আপনি আছে বেস বর্গ পদ্ধতি ঘোষণা করার protected

তারপরে, আপনাকে কোনও মন্তব্যের মাধ্যমে ইঙ্গিত করার কুৎসিত অভিযাত্রী নিতে হবে যে পদ্ধতিটি ওভাররাইড করা উচিত তবে কল করা উচিত নয়।

class Base
{
 ...
 protected:
 // chained virtual function!
 // call in your derived version but nowhere else.
 // Use set_data instead
 virtual void cleanup() { /* do something */ }
 ...

এইভাবে হার্ব সটারের গাইডলাইন # 3 ... তবে ঘোড়া যাই হোক না কেন শস্যাগার বাইরে।

আপনি যখন protectedকোনও কিছু ঘোষণা করেন আপনি সুরক্ষিত ইন্টার্নালগুলি বুঝতে এবং সঠিকভাবে ব্যবহার করতে কোনও উদ্ভূত শ্রেণীর লেখকের উপর স্পষ্টভাবে বিশ্বাস স্থাপন করছেন, ঠিক যেভাবে কোনও friendঘোষণাপত্র privateসদস্যদের প্রতি গভীর বিশ্বাসকে বোঝায় ।

যে বিশ্বাসীরা সেই বিশ্বাস লঙ্ঘন করে খারাপ আচরণ পান (যেমন আপনার ডকুমেন্টেশনগুলি পড়ার বিরক্ত না করে 'ক্লুলেস' হিসাবে লেবেলযুক্ত) কেবল তাদেরই দোষ দেওয়া উচিত।

হালনাগাদ : আমার কিছু প্রতিক্রিয়া ছিল যা দাবি করে যে আপনি ব্যক্তিগত ভার্চুয়াল ফাংশনগুলি ব্যবহার করে এইভাবে ভার্চুয়াল ফাংশন বাস্তবায়ন "চেইন" করতে পারেন। যদি তা হয় তবে আমি অবশ্যই এটি দেখতে চাই।

আমি যে সি ++ সংকলকগুলি অবশ্যই স্পষ্টভাবে ব্যবহার করি তা উত্সযুক্ত শ্রেণি প্রয়োগের কোনও বেসরকারী বেস শ্রেণীর প্রয়োগকে কল করতে দেয় না।

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


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

1
আমি যা বলছিলাম তা নয়। তবে বেসরকারী বেস শ্রেণীর ফাংশনটি কল করার প্রয়োজন ছাড়াই আপনি একই কোড অর্জনের জন্য আপনার
কোডটির

3
আপনার উদাহরণে আপনি এর আচরণ প্রসারিত করতে চান set_data। নির্দেশাবলী m_data = ndata;এবং cleanup();এইভাবে একটি আক্রমণকারী হিসাবে বিবেচিত হতে পারে যা সমস্ত প্রয়োগের জন্য অবশ্যই রাখা উচিত। অতএব cleanup()নন-ভার্চুয়াল এবং ব্যক্তিগত করুন। ভার্চুয়াল এবং আপনার শ্রেণীর এক্সটেনশন পয়েন্টের অন্য একটি ব্যক্তিগত পদ্ধতিতে একটি কল যুক্ত করুন। এখন আপনার উত্পন্ন ক্লাসগুলির বেসের cleanup()আর কল করার দরকার নেই, আপনার কোড পরিষ্কার থাকে এবং আপনার ইন্টারফেসটি ভুলভাবে ব্যবহার করা শক্ত।
সিজি

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

2
তাহলে আসুন একমত হতে সম্মত হন;)
সিজি

9

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

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

public:
  void NonVirtualCalc(...)
  {
    // Setup
    PrivateVirtualCalcCall(...);
    // Clean up
  }

আমি মনে করি এটি একটি খুব আকর্ষণীয় ডিজাইনের প্যাটার্ন এবং আমি নিশ্চিত যে অতিরিক্ত নিয়ন্ত্রণ কীভাবে কার্যকর তা আপনি দেখতে পারবেন।

  • ভার্চুয়াল ফাংশন কেন private? সর্বোত্তম কারণ হ'ল আমরা ইতিমধ্যে একটি publicমুখোমুখি পদ্ধতি সরবরাহ করেছি ।
  • কেন protectedআমি এটিকে সহজভাবে তৈরি করব না যাতে আমি অন্যান্য আকর্ষণীয় জিনিসের জন্য পদ্ধতিটি ব্যবহার করতে পারি? আমি মনে করি এটি সর্বদা আপনার নকশার উপর নির্ভর করে এবং আপনি কীভাবে বেস ক্লাসটি ফিট করে বিশ্বাস করেন I ইতিমধ্যে অন্য সবকিছুর যত্ন নেওয়া হয়েছে। এছাড়াও, এনক্যাপসুলেশনের বিষয়টি রয়েছে।

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


3

আমি তাদের ব্যবহার শেষ ক্লাসের ব্যবহারকারীদের যেমন কোনও ছিদ্র প্রকাশ না করে ভিত্তিক শ্রেণীর জন্য "শূন্যস্থান পূরণ" করতে উত্পন্ন ক্লাসগুলিকে অনুমতি দেওয়ার জন্য ব্যবহার করি। উদাহরণস্বরূপ, আমার কাছে একটি সাধারণ বেস থেকে প্রাপ্ত উচ্চতর রাষ্ট্রীয় অবজেক্ট রয়েছে, যা কেবলমাত্র সামগ্রিক রাষ্ট্র মেশিনের 2/3 প্রয়োগ করতে পারে (উত্পন্ন শ্রেণিগুলি টেমপ্লেট যুক্তির উপর নির্ভর করে অবশিষ্ট 1/3 সরবরাহ করে এবং বেসটি কোনও টেমপ্লেট হতে পারে না অন্যান্য কারণ)।

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

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

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