সি ++ ভার্চুয়াল ফাংশনগুলি নিরাপদে ওভাররাইড করুন


100

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

এই উদাহরণটি ধরুন:

class parent {
public:
  virtual void handle_event(int something) const {
    // boring default code
  }
};

class child : public parent {
public:
  virtual void handle_event(int something) {
    // new exciting code
  }
};

int main() {
  parent *p = new child();
  p->handle_event(1);
}

এখানে parent::handle_event()পরিবর্তে বলা হয় child::handle_event(), কারণ সন্তানের পদ্ধতিটি constঘোষণাকে বাদ দেয় এবং তাই একটি নতুন পদ্ধতি ঘোষণা করে। এটি ফাংশন নামের একটি টাইপও হতে পারে বা পরামিতিগুলির ধরণের মধ্যে কিছু ছোট পার্থক্য difference বেস ক্লাসের ইন্টারফেস পরিবর্তিত হয় এবং কোথাও কোথাও প্রাপ্ত কিছু শ্রেণীর পরিবর্তনটি প্রতিবিম্বিত করতে আপডেট না করা হলে এটি সহজেই ঘটতে পারে।

এই সমস্যা এড়ানোর কোনও উপায় আছে কি, আমি কি আমার কাছে এটি পরীক্ষা করার জন্য কোনওভাবে সংকলক বা অন্য কোনও সরঞ্জাম বলতে পারি? কোনও সহায়ক সংকলক পতাকা (সাধারণত জি ++ এর জন্য)? কীভাবে আপনি এই সমস্যাগুলি এড়াতে পারেন?


2
দুর্দান্ত প্রশ্ন, আমি বুঝতে চেষ্টা করছি যে আমার শিশু শ্রেণির ক্রিয়াকলাপটি কেন এখন এক ঘন্টা থেকে ডাকা হয় না!
আকাশ মনকার

উত্তর:


89

G ++ 4.7 যেহেতু এটি নতুন সি ++ 11 overrideকীওয়ার্ডটি বুঝতে পারে :

class child : public parent {
    public:
      // force handle_event to override a existing function in parent
      // error out if the function with the correct signature does not exist
      void handle_event(int something) override;
};

@ হিড়শহর্নসালজ: আমি দেখতে পেয়েছি যে আপনি যখন ফাংশনটি প্রয়োগের শেষে হ্যান্ডেল_ভেন্ট ফাংশনটি প্রয়োগ করেন এবং আপনি ওভাররাইড যুক্ত করেন, জি ++ একটি ত্রুটি দেয়; ওভাররাইড কীওয়ার্ড অনুসরণ করে আপনি যদি ক্লাস ঘোষণায় কোনও ইনলাইন ফাংশন বাস্তবায়ন সরবরাহ করেন তবে সবকিছু ঠিক আছে। কেন?
h9uest

3
@ h9uest overrideঅবশ্যই সংজ্ঞাতে ব্যবহার করা উচিত। একটি ইনলাইন বাস্তবায়ন সংজ্ঞা এবং বাস্তবায়ন উভয়ই তাই ঠিক আছে।
গুন্থার পাইজ

@ হিরছহর্নসালজ হ্যাঁ আমি জি ++ দ্বারা একই ত্রুটি পেয়েছি। একটি পক্ষের নোট, যদিও: আপনি এবং জি ++ ত্রুটি উভয়ই "শব্দ সংজ্ঞা" শব্দটি ব্যবহার করেছেন - আমরা কি "ঘোষণা" (ration ঘোষণা, সংজ্ঞা definition জোড়া) ব্যবহার করব না? আপনি "সংজ্ঞা ও বাস্তবায়ন" বলে নিজেকে এই নির্দিষ্ট প্রসঙ্গে নিজেকে পরিষ্কার করে দিয়েছেন, তবে আমি কেবল অবাকই করি কেন সি ++ সম্প্রদায় হঠাৎ ক্লাসের শর্তাবলী পরিবর্তন করার সিদ্ধান্ত নেয়?
h9uest

20

সি # এর overrideকীওয়ার্ডের মতো কিছু সি ++ এর অংশ নয়।

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


2
এটি যদি আপনি ভিজ্যুয়াল সি ++ ব্যবহার করেন
স্টিভ রোয়ে

4
ভিজ্যুয়াল সি ++ ব্যবহার করা সি ++ এ কোনও overrideকীওয়ার্ড তৈরি করে না ; এর অর্থ হতে পারে যে আপনি এমন কিছু ব্যবহার করছেন যা কিছু অবৈধ সি ++ উত্স কোডটি সংকলন করতে পারে। ;)
সিবি বেইলি

3
ওভাররাইডটি অবৈধ সি ++ এর অর্থ মানটি ভুল, এবং ভিজ্যুয়াল সি ++ নয়
জন

2
@ জন: ঠিক আছে, এখন দেখছি আপনি কী গাড়ি চালাচ্ছিলেন। ব্যক্তিগতভাবে আমি সি # শৈলীর overrideকার্যকারিতা নিতে বা ছেড়ে দিতে পারি ; ব্যর্থ ওভাররাইডগুলির সাথে আমার খুব কমই সমস্যা হয়েছিল এবং তারা নির্ণয় এবং সংশোধন করা তুলনামূলক সহজ easy আমার মনে হয় আমি একমত হব না ভিসি ++ ব্যবহারকারীদের এটি ব্যবহার করা উচিত। আমি পছন্দ করি যে সমস্ত প্ল্যাটফর্মগুলিতে সি ++ এর মতো দেখতে সি ++ এর মতো দেখতেও যদি একটি নির্দিষ্ট প্রকল্পের পোর্টেবল হওয়ার প্রয়োজন না হয়। এটা তোলে এর মূল্য তিনি লক্ষ করেন সি ++ 0x থাকবে [[base_check]], [[override]]এবং [[hiding]]বৈশিষ্ট্যাবলী যাতে আপনি চেক ওভাররাইড করার জন্য ইচ্ছা হলে নির্বাচন করতে পারেন।
সিবি বেইলি

5
অদ্ভুতভাবে যথেষ্ট, মন্তব্য পর বছর দুয়েক ভিসি ++, ব্যবহার দেখা যায় না overrideএকটি শব্দ মনে হয় এটা করেনি । ঠিক আছে, একটি সঠিক কীওয়ার্ড নয় বরং সি ++ 11-তে একটি বিশেষ পরিচয়কারী। মাইক্রোসফ্ট এটিকে একটি বিশেষ কেস overrideতৈরি করতে এবং বৈশিষ্ট্যের জন্য সাধারণ ফর্ম্যাটটি অনুসরণ করতে এবং স্ট্যান্ডার্ডে পরিণত করার জন্য যথেষ্ট কঠোরভাবে চাপ দিয়েছে :)
ডেভিড রদ্রিগেজ - ড্রিবিয়াস

18

আমি যতদূর জানি, আপনি কি কেবল এটি বিমূর্ত করতে পারবেন না?

class parent {
public:
  virtual void handle_event(int something) const = 0 {
    // boring default code
  }
};

আমি ভেবেছিলাম আমি www.parashift.com এ পড়েছি যে আপনি আসলে একটি বিমূর্ত পদ্ধতি প্রয়োগ করতে পারেন। যা ব্যক্তিগতভাবে আমার কাছে বোধগম্য হয়, এটি কেবলমাত্র সাবক্লাসগুলিই এটি প্রয়োগ করতে বাধ্য করে, এটি নিজেই বাস্তবায়নের অনুমতি না দেওয়া সম্পর্কে কেউ কিছু বলেনি।


কেবলমাত্র এখন আমি বুঝতে পেরেছি যে এটি কেবল ধ্বংসকারীদের চেয়ে বেশি কাজ করে! দুর্দান্ত খুঁজে।
স্ট্র্যাজার

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

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

এটি প্রাপ্ত পদ্ধতির (বলি BaseClass::method()) DerivedClass::method()উদাহরণ হিসাবে ডায়াল্ট মানের জন্য বেস পদ্ধতির (বলি ) ডাকতেও বাধা দেয় ।
নারকোলেসিকো

11

এমএসভিসিতে আপনি সিএলআর overrideকিওয়ার্ডটি সিএলআরের জন্য সংকলন না করেও ব্যবহার করতে পারেন ।

জি ++ তে, প্রয়োগের প্রত্যক্ষ উপায় নেই যে সব ক্ষেত্রেই; অন্যান্য ব্যক্তিরা কীভাবে স্বাক্ষর পার্থক্যগুলি ব্যবহার করে তা ধরতে ভাল উত্তর দিয়েছেন -Woverloaded-virtual। ভবিষ্যতের সংস্করণে, কেউ __attribute__ ((override))সি ++ 0x সিনট্যাক্স ব্যবহার করে এর মতো সমতুল্য বা সমতুল্য যুক্ত করতে পারে ।


9

এমএসভিসি ++ এ আপনি কীওয়ার্ড ব্যবহার করতে পারেনoverride

class child : public parent {
public:
  virtual void handle_event(int something) <b>override</b> {
    // new exciting code
  }
};

override এমএসভিসি ++ এ নেটিভ এবং সিএলআর কোড উভয়ের জন্য কাজ করে।


5

ফাংশনটিকে বিমূর্ত করে তুলুন, যাতে উত্পন্ন শ্রেণীর কাছে এটি ওভাররাইড করা ছাড়া অন্য কোনও উপায় না থাকে।

@ রে আপনার কোডটি অবৈধ।

class parent {
public:
  virtual void handle_event(int something) const = 0 {
    // boring default code
  }
};

বিমূর্ত ফাংশনগুলিতে ইনলাইন সংজ্ঞায়িত সংস্থাগুলি থাকতে পারে না। এটি হয়ে ওঠতে হবে ified

class parent {
public:
  virtual void handle_event(int something) const = 0;
};

void parent::handle_event( int something ) { /* do w/e you want here. */ }

3

আমি আপনার যুক্তিতে কিছুটা পরিবর্তন আনতে পরামর্শ দেব। আপনার কী অর্জন করা উচিত তার উপর নির্ভর করে এটি কাজ করতে পারে বা নাও পারে।

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

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


2

আপনার সংকলকটির একটি সতর্কতা থাকতে পারে যে এটি যদি উত্পন্ন শ্রেনী ফাংশনটি গোপন হয়ে যায় তবে তা উত্পন্ন করতে পারে। এটি যদি করে, এটি সক্ষম করুন। এটি প্যারামিটার তালিকার দ্বন্দ্ব এবং পার্থক্যগুলি ধরবে। দুর্ভাগ্যক্রমে এটি কোনও বানান ত্রুটিটি উদঘাটন করবে না।

উদাহরণস্বরূপ, এটি মাইক্রোসফ্ট ভিজ্যুয়াল সি ++ এ C4263 সতর্ক করছে।


1

সি ++ 11 overrideকীওয়ার্ড যখন ডেরাইভেড ক্লাসের ভিতরে ফাংশন ঘোষণার সাথে ব্যবহার করা হয়, তখন এটি সংকলকটিকে ঘোষিত ফাংশনটি কিছু বেস ক্লাস ফাংশনটি ওভাররাইড করে তা পরীক্ষা করতে বাধ্য করে। অন্যথায়, সংকলক একটি ত্রুটি নিক্ষেপ করবে।

তাই আপনি overrideগতিশীল পলিমারফিজম (ফাংশন ওভাররাইডিং) নিশ্চিত করতে নির্দিষ্টকরণকারক ব্যবহার করতে পারেন ।

class derived: public base{
public:
  virtual void func_name(int var_name) override {
    // statement
  }
};
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.