কেন সি ++ 11 মুছে ফাংশনগুলি ওভারলোড রেজোলিউশনে অংশ নেয়?


91

কেন সি ++ 11 " deleteডি" ফাংশনগুলি ওভারলোড রেজোলিউশনে অংশ নেয় ?
কেন এটি দরকারী? বা অন্য কথায়, এগুলি পুরো মোছার পরিবর্তে কেন লুকানো থাকে?



উত্তর:


117

= deleteসিনট্যাক্সের অর্ধেক উদ্দেশ্য হ'ল নির্দিষ্ট পরামিতিগুলির সাথে লোকদের নির্দিষ্ট ফাংশনগুলি কল করতে বাধা দেওয়া। এটি সাধারণত নির্দিষ্ট নির্দিষ্ট পরিস্থিতিতে অন্তর্নিহিত রূপান্তরগুলি রোধ করার জন্য। কোনও নির্দিষ্ট ওভারলোড নিষিদ্ধ করার জন্য, এটি ওভারলোড রেজোলিউশনে অংশ নিতে হবে।

আপনি যে উত্তরটি উদ্ধৃত করেছেন এটি একটি নিখুঁত উদাহরণ দেয়:

struct onlydouble {
  onlydouble(std::intmax_t) = delete;
  onlydouble(double);
};

যদি deleteপুরোপুরি ফাংশনটি সরিয়ে ফেলা হয়, এটি = deleteসিনট্যাক্সটিকে এর সমান করে তুলবে :

struct onlydouble2 {
  onlydouble2(double);
};

আপনি এটি করতে পারেন:

onlydouble2 val(20);

এটি আইনী সি ++। সংকলকটি সমস্ত নির্মাণকারীকে দেখবে; এগুলির মধ্যে কেউই সরাসরি কোনও পূর্ণসংখ্যার প্রকার নেয় না। তবে তাদের মধ্যে একটি এটি অন্তর্নিহিত রূপান্তরের পরে নিতে পারে। সুতরাং এটি কল করব।

onlydouble val(20);

এই না আইনি সি ++। সংকলকটি deleted সহ সমস্ত কন্সট্রাক্টরকে দেখবে । এটি std::intmax_t(যা কোনও সংখ্যার আক্ষরিক সাথে হুবহু মিলবে) এর মাধ্যমে একটি সঠিক মিল দেখবে । সুতরাং সংকলক এটি নির্বাচন করবে এবং তারপরে তাত্ক্ষণিকভাবে একটি ত্রুটি জারি করবে, কারণ এটি একটি deleteডি ফাংশন নির্বাচন করেছে ।

= delete"" আমি এটিকে নিষেধ করি ", নিছক নয়" "এর অস্তিত্ব নেই" " এটি অনেক শক্তিশালী বক্তব্য।

আমি জিজ্ঞাসা করছিলাম কেন সি ++ স্ট্যান্ডার্ড বলছে = মুছে ফেলার অর্থ "এটি বিদ্যমান নয়" এর পরিবর্তে "আমি এটিকে নিষেধ করি"

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

ব্যাকরণ সুস্পষ্টভাবে "এটি বিদ্যমান নেই" থাকার মাধ্যমে আপনি যে কার্যকারিতা অর্জন করবেন তা হ'ল কারওর পরে এটির অস্তিত্ব ঘোষণা করে বাধা দেওয়া। এবং এটি নিজস্ব ব্যাকরণ প্রয়োজন যথেষ্ট দরকারী নয়।

অন্যথায় অনুলিপি দেওয়ার কোনও উপায় নেই যে অনুলিপি নির্মাণকারীর অস্তিত্ব নেই এবং এর অস্তিত্ব অযৌক্তিক দ্বিধা তৈরি করতে পারে।

অনুলিপি নির্মাণকারী একটি বিশেষ সদস্য ফাংশন। প্রতিটি শ্রেণীর সর্বদা একটি অনুলিপি নির্মাণকারী থাকে। ঠিক যেমন তাদের কাছে সর্বদা একটি অনুলিপি অ্যাসাইনমেন্ট অপারেটর, মুভ কনস্ট্রাক্টর ইত্যাদি থাকে have

এই ফাংশন বিদ্যমান; তাদের ফোন করা বৈধ কিনা তা কেবল প্রশ্ন। আপনি যদি = deleteএটির চেষ্টা করে বোঝানোর চেষ্টা করেন যে তাদের অস্তিত্ব নেই, তবে স্পেসিফিকেশনটি কোনও ফাংশনের অস্তিত্ব না থাকার জন্য এর অর্থ কী তা ব্যাখ্যা করতে হবে। এটি কোনও ধারণা নয় যা স্পেসিফিকেশন পরিচালনা করে।

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

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

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

এবং আবার প্রথম অংশটি পুনরায় পড়ুন "ফাংশনের অস্তিত্ব নেই" দিয়ে আপনি এটি করতে পারবেন না । এটি সেইরূপে সংজ্ঞায়িত করার কারণেই এটি অন্য কারণ: কারণ = deleteসিনট্যাক্সের প্রধান ব্যবহারের ক্ষেত্রে অন্যতম হল ব্যবহারকারীকে নির্দিষ্ট প্যারামিটার ধরণের ব্যবহার করতে, স্পষ্টতই কাস্ট করতে বাধ্য করা এবং এর বাইরেও। মূলত, অন্তর্নিহিত ধরণের রূপান্তর ফেইল করতে।

আপনার পরামর্শটি তা করবে না।


4
@ মেহরদাদ: কেন = মুছে ফেলার মতো আপনি যেভাবে কাজ করেন না সে সম্পর্কে যদি আপনার আরও স্পষ্টতা প্রয়োজন হয় তবে আপনার কী ভাবেন = মুছতে হবে তার সঠিক শব্দার্থ সম্পর্কে আপনাকে আরও পরিষ্কার হওয়া দরকার । এটি কি "ভান করা উচিত আমি কখনই এই লাইনটি লিখিনি?" নাকি এটি অন্য কিছু হওয়া উচিত?
নিকল বোলাস

4
না, আমি বোঝাতে = deleteচাইছি " আমি এই সদস্যটির অস্তিত্ব নেই" বোঝাতে চাইছি, যা বোঝায় এটি ওভারলোড রেজোলিউশনে অংশ নিতে পারে না।
ব্যবহারকারী541686

6
@ মেহরদাদ: এবং এটি আমার মূল বিন্দুতে ফিরে যায়, যার কারণেই আমি এটি পোস্ট করেছি: যদি = delete"এই সদস্যটির অস্তিত্ব নেই" বোঝানো হয়, তবে আমি যে প্রথম উদাহরণটি পোস্ট করেছি তা মানুষকে onlydoubleনির্মাণকারীর কাছে পূর্ণসংখ্যার দিক থেকে আটকাতে সক্ষম হবে না , যেহেতু onlydoubleমুছে ফেলা ওভারলোডটি বিদ্যমান থাকবে না । এটি ওভারলোড রেজোলিউশনে অংশ নেবে না এবং সুতরাং এটি আপনাকে পূর্ণসংখ্যার মধ্য দিয়ে যাওয়া থেকে বিরত রাখবে না। যা = deleteসিনট্যাক্সের বিন্দুটির অর্ধেক: এটি বলতে সক্ষম হতে, "আপনি এই ফাংশনটিতে এক্সকে পুরোপুরি পাস করতে পারবেন না।"
নিকল বোলাস

4
@ মেহরদাদ: এই যুক্তি অনুসারে, আপনার এখানের দরকার কেন =delete? সর্বোপরি, আমরা ঠিক একই জিনিসটি করে "অনুলিপিযোগ্য" বলতে পারি: অনুলিপি নির্মাণকারী / কার্যনির্বাহী ব্যক্তিগত হিসাবে ঘোষণা করে। এছাড়াও, নোট করুন যে কোনও কিছু ব্যক্তিগত হিসাবে ঘোষণা করা অবিশ্বাস্য নয়; শ্রেণীর মধ্যে কোড এখনও কল করতে পারেন। সুতরাং এটি যেমন হয় না = delete। না, = deleteসিনট্যাক্স আমাদের এমন কিছু করার অনুমতি দেয় যা এর আগে আরও বেশি স্পষ্ট এবং যুক্তিসঙ্গত উপায়ে অত্যন্ত অসুবিধে এবং অনিবার্য ছিল।
নিকল বোলাস

4
@ মেহরদাদ: কারণ পরবর্তীটি সম্ভব : এটি "এটি ঘোষণা করবেন না" বলা হয় called তাহলে এর অস্তিত্ব থাকবে না। কেন আমাদের প্রাইভেট আপত্তি না দিয়ে একটি ওভারলোড আড়াল করার জন্য সিনট্যাক্সের প্রয়োজন ... আপনি কি সত্যিই জিজ্ঞাসা করছেন যে একই প্রভাব পেতে অন্য কোনও বৈশিষ্ট্যকে অপব্যবহার করার পরিবর্তে আমাদের স্পষ্টভাবে কিছু বলার উপায় থাকা উচিত কেন ? কোডটি পড়া কারও কাছে এটি কেবল আরও সুস্পষ্ট এটি কোডটি ব্যবহারকারীর কাছে আরও সহজেই বোধগম্য হয়ে ওঠে এবং লেখার পক্ষে আরও সহজ করে তোলে, পাশাপাশি কাজের সমাধানের সমস্যাগুলিও ঠিক করে দেয়। আমরা না প্রয়োজন হয় lambdas।
নিকল বোলাস

10

সি ++ ওয়ার্কিং ড্রাফ্ট 2012-11-02 এই নিয়মের পিছনে যুক্তি সরবরাহ করে না, কেবল কয়েকটি উদাহরণ

8.4.3 মুছে ফেলা সংজ্ঞাগুলি [dcl.fct.def.delete]
...
3 [ উদাহরণ : কেউ অ-ডিফল্ট সূচনা এবং অ-অবিচ্ছেদ্য সূচনা প্রয়োগ করতে পারে এর সাথে

struct onlydouble {  
  onlydouble() = delete; // OK, but redundant  
  onlydouble(std::intmax_t) = delete;  
  onlydouble(double);  
};  

- শেষ উদাহরণ ]
[ উদাহরণস্বরূপ : একটি শ্রেণীর জন্য নতুন কোনও ব্যবহারকারী-ঘোষিত অপারেটরের মুছে ফেলা সংজ্ঞা ব্যবহার করে নির্দিষ্ট নতুন এক্সপ্রেশনগুলিতে কোনও শ্রেণীর ব্যবহার প্রতিরোধ করতে পারে।

struct sometype {  
  void *operator new(std::size_t) = delete;  
  void *operator new[](std::size_t) = delete;  
};  
sometype *p = new sometype; // error, deleted class operator new  
sometype *q = new sometype[3]; // error, deleted class operator new[]  

- শেষ উদাহরণ ]
[ উদাহরণস্বরূপ : কপি কন্সট্রাক্টর এবং অনুলিপি নিয়োগের অপারেটরের মুছে ফেলা সংজ্ঞাগুলি ব্যবহার করে এবং তারপরে মুভ কনস্ট্রাক্টর এবং মুভ অ্যাসাইনমেন্ট অপারেটরের ডিফল্ট সংজ্ঞা প্রদান করে একটি ক্লাসকে অনিবার্য, অর্থাৎ সরানো কেবলমাত্র তৈরি করতে পারে।

struct moveonly {  
  moveonly() = default;  
  moveonly(const moveonly&) = delete;  
  moveonly(moveonly&&) = default;  
  moveonly& operator=(const moveonly&) = delete;  
  moveonly& operator=(moveonly&&) = default;  
  ~moveonly() = default;  
};  
moveonly *p;  
moveonly q(*p); // error, deleted copy constructor  

- শেষ উদাহরণ ]


4
উদাহরণগুলি থেকে যুক্তিটি খুব স্পষ্ট মনে হয়, আপনি কি ভাবেন না?
জেসি শুভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.