সি ++ এ 'অবশেষে' নির্মাণ কেন হয় না?


57

সি ++ এ ব্যতিক্রম হ্যান্ডলিং চেষ্টা / নিক্ষেপ / ধরা সীমাবদ্ধ। অবজেক্ট প্যাসকাল, জাভা, সি # এবং পাইথনের বিপরীতে, এমনকি সি ++ 11-তেও এই নির্মাণটি finallyকার্যকর করা হয়নি।

আমি "ব্যতিক্রমী নিরাপদ কোড" নিয়ে আলোচনা করে প্রচুর সি ++ সাহিত্য দেখেছি। লিপম্যান লিখেছেন যে ব্যতিক্রমী নিরাপদ কোড একটি গুরুত্বপূর্ণ তবে উন্নত, কঠিন বিষয়, যা তার প্রাইমারের সীমার বাইরে - যা বোঝাচ্ছে যে নিরাপদ কোডটি সি ++ এর পক্ষে মৌলিক নয়। ভেষজ সুটার তার ব্যতিক্রমী সি ++ বিষয়টিতে 10 টি অধ্যায়টি উত্সর্গ করে!

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

সি ++ 11 এ প্রয়োগ করা সমস্ত 'ঘণ্টা এবং হুইসেল' বিবেচনা করে আমি অবাক হয়ে গেলাম যে 'অবশেষে' এখনও নেই।

সুতরাং, কেন finallyকনস্ট্রাক্টটি কখনই সি ++ এ প্রয়োগ করা হয়নি? এটি উপলব্ধি করা খুব জটিল বা উন্নত ধারণা নয় এবং প্রোগ্রামারকে 'ব্যতিক্রমী নিরাপদ কোড' লিখতে সহায়তা করার জন্য দীর্ঘ পথ অবলম্বন করে।


25
কেন না শেষ পর্যন্ত? কারণ আপনি ধ্বংসকারীদের এমন জিনিস প্রকাশ করেন যা বস্তুটি (বা স্মার্ট পয়েন্টার) সুযোগ ছাড়লে স্বয়ংক্রিয়ভাবে আগুন দেয়। ধ্বংসকারীরা পরিশেষে to to এর চেয়ে উচ্চতর, কারণ এটি ক্লিনআপ যুক্তি থেকে কর্মপ্রবাহকে পৃথক করে। ঠিক যেমন আপনি কলগুলি () মুক্ত করতে কল করতে চান না তেমন কোনও জঞ্জাল সংগ্রহ করা ভাষায় আপনার কর্মপ্রবাহকে চাঙ্গা করতে পারে।
মাইকে 30


8
প্রশ্ন জিজ্ঞাসা করা হচ্ছে, " finallyসি ++ তে কেন নেই এবং এর জায়গায় ব্যতিক্রম হ্যান্ডলিংয়ের জন্য কোন কৌশলগুলি ব্যবহার করা হয়?" বৈধ এবং এই সাইটের জন্য বিষয়। আমি মনে করি বিদ্যমান উত্তরগুলি এটিকে ভালভাবে কভার করে। এটিকে "কি সি ++ ডিজাইনারদের finallyসার্থক না করার কারণগুলির কারণগুলিতে আলোচনায় পরিণত করা ?" এবং " finallyসি ++ এ যুক্ত করা উচিত ?" এবং প্রশ্ন এবং প্রতিটি উত্তর সম্পর্কে মন্তব্য জুড়ে আলোচনা চালিয়ে এই প্রশ্নোত্তর সাইটের মডেল ফিট করে না।
জোশ কেলি

2
যদি আপনার অবশেষে হয়, আপনার ইতিমধ্যে উদ্বেগের বিভাজন রয়েছে: প্রধান কোড ব্লকটি এখানে রয়েছে, এবং ক্লিনআপ উদ্বেগটি এখানে যত্ন নেওয়া হয়েছে।
কাজ

2
@Kaz। পার্থক্য সুস্পষ্ট পরিষ্কার আপ জড়িত। একজন ডেস্ট্রাক্টর আপনাকে সাদামাটা পুরানো আদিমাগুলি কীভাবে পরিষ্কার করা হয় তার সমানভাবে স্বয়ংক্রিয়ভাবে সাফ দেয় it আপনার কোনও সুস্পষ্ট ক্লিন আপ কল করার দরকার নেই এবং আপনার মূল যুক্তিতে মনোনিবেশ করতে পারেন। আপনি যদি চেষ্টা / শেষ অবধি স্ট্যাক বরাদ্দ আদিমগুলি পরিষ্কার করতে হয় তবে এটি কতটা সংশ্লেষিত হবে তা কল্পনা করুন। অন্তর্নিহিত পরিষ্কার আপ উচ্চতর। বেনাম কর্মের সাথে শ্রেণি সিনট্যাক্সের তুলনা প্রাসঙ্গিক নয়। যদিও একটি ফাংশনে প্রথম শ্রেণীর ফাংশনগুলি পাস করে যা একটি হ্যান্ডেল প্রকাশ করে তা ম্যানুয়াল ক্লিনআপকে কেন্দ্রিয় করতে পারে।
মাইকে 30

উত্তর:


57

@ নেমঞ্জার উত্তরের উপর কিছু অতিরিক্ত মন্তব্য হিসাবে (যা এটি স্ট্রোস্ট্রপের উদ্ধৃতি দিয়েছিল, আপনি যতটা উত্তর পেতে পারেন তেমন উত্তম):

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

যে ভাষাতে try/ ব্যবহার করে finally, কোডটি এর মতো দেখতে পারে:

database.Open();
try {
    database.DoRiskyOperation();
} finally {
    database.Close();
}

সরল ও সোজা। তবে কয়েকটি অসুবিধা রয়েছে:

  • যদি ভাষাটির প্রতিরোধমূলক ডেস্ট্রাক্টর না থাকে তবে আমাকে সর্বদাfinally ব্লকটি লিখতে হবে , অন্যথায় আমি সংস্থানগুলি ফাঁস করব।
  • যদি DoRiskyOperationকোনও একক পদ্ধতির কলের চেয়ে বেশি হয় - যদি আমার tryব্লকটিতে কিছু প্রসেসিং থাকে - তবে Closeঅপারেশনটি অপারেশন থেকে কিছুটা দূরে সরে যেতে পারে Open। আমি আমার অধিগ্রহণের ঠিক পাশেই আমার ক্লিনআপ লিখতে পারি না।
  • যদি আমার বেশ কয়েকটি সংস্থান থাকে যেগুলি অধিগ্রহণের প্রয়োজন হয় তবে একটি ব্যতিক্রম-নিরাপদ উপায়ে মুক্ত করা যায়, আমি বেশ কয়েকটি স্তর try/ finallyব্লকের গভীরে শেষ করতে পারি।

সি ++ পদ্ধতির মতো দেখতে পাবেন:

ScopedDatabaseConnection scoped_connection(database);
database.DoRiskyOperation();

এটি finallyপদ্ধতির সমস্ত অসুবিধাগুলি সম্পূর্ণরূপে সমাধান করে। এর নিজস্ব কিছু অসুবিধা রয়েছে তবে সেগুলি তুলনামূলকভাবে অপ্রতুল:

  • আপনার ScopedDatabaseConnectionনিজের ক্লাসটি লেখার একটি ভাল সুযোগ রয়েছে । তবে এটি একটি খুব সহজ বাস্তবায়ন - কোডের কেবল 4 বা 5 লাইন।
  • এটির সাথে একটি অতিরিক্ত স্থানীয় পরিবর্তনশীল তৈরি করা জড়িত - যা "আপনার গণ্ডগোল পরিষ্কার করার জন্য নিয়মিতভাবে তাদের ধ্বংসকারীদের উপর নির্ভর করতে ক্লাস তৈরি করা এবং ধ্বংস করা" খুব খারাপ "- আপনার মন্তব্যের উপর ভিত্তি করে আপনি কোনও ভক্ত নন, তবে একটি ভাল সংকলক অপ্টিমাইজ করবে অতিরিক্ত স্থানীয় পরিবর্তনশীল জড়িত অতিরিক্ত কাজগুলির বাইরে। ভাল সি ++ ডিজাইন এই ধরণের অপ্টিমাইজেশনের উপর অনেক নির্ভর করে।

ব্যক্তিগতভাবে, এই সুবিধাগুলি এবং অসুবিধাগুলি বিবেচনা করে আমি RAII কে অনেক বেশি পছন্দনীয় কৌশল বলে মনে করি finally। আপনার মাইলেজ পরিবর্তিত হতে পারে.

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


8
সি # এর usingবিবৃতি রয়েছে, যা IDisposableইন্টারফেস প্রয়োগকারী যে কোনও বস্তুটি স্বয়ংক্রিয়ভাবে পরিষ্কার করে । সুতরাং এটির ভুল হওয়া সম্ভব হলেও এটি সঠিকভাবে পাওয়া খুব সহজ।
রবার্ট হার্ভে

18
অস্থায়ী রাষ্ট্র পরিবর্তন বিপরীতের যত্ন নেওয়ার জন্য সম্পূর্ণ নতুন ক্লাস লিখতে হবে, একটি ডিজাইন আইডিয়ম ব্যবহার করে যা একটি try/finallyকনস্ট্রাক্ট দিয়ে সংকলক দ্বারা প্রয়োগ করা হয় কারণ সংকলক কোনও try/finallyনির্মাণকে প্রকাশ করে না এবং এটিতে প্রবেশ করার একমাত্র উপায় ক্লাস-ভিত্তিক ডিজাইন প্রতিমা, একটি "সুবিধা" নয়; এটি একটি বিমূর্ত বিপরীতে খুব সংজ্ঞা।
ম্যাসন হুইলার

15
@ ম্যাসনভিয়েল - উম্ম, আমি বলিনি যে একটি নতুন ক্লাস লিখতে সুবিধা হয়। আমি বললাম এটা অসুবিধা। ভারসাম্য বজায় রাখার পরেও আমি আরআইআইআই ব্যবহার করতে পছন্দ করি finally। যেমনটি আমি বলেছিলাম, আপনার মাইলেজ আলাদা হতে পারে।
জোশ কেলি

7
@ জোশকেলি: 'গুড সি ++ ডিজাইন এই ধরণের অপ্টিমাইজেশনের উপর অনেক বেশি নির্ভর করে।' এক্সট্রেনাস কোডের গবস লিখে এবং তারপরে সংকলক অপ্টিমাইজেশনের উপর নির্ভর করে গুড ডিজাইন ?! আইএমও এটি ভাল ডিজাইনের বিরোধী। ভাল ডিজাইনের মৌলিকগুলির মধ্যে সংক্ষিপ্ত, সহজেই পঠনযোগ্য কোড। ডিবাগ করা কম, রক্ষণাবেক্ষণ কম, ইত্যাদি ইত্যাদি ইত্যাদি আপনার কোড গব লিখতে হবে না এবং তারপরে সমস্তটি দূরে সরিয়ে দেওয়ার জন্য সংকলকটির উপর নির্ভর করা উচিত নয় - আইএমও যা কোনও অর্থই দেয় না!
ভেক্টর

14
@ মাইকি: সুতরাং কোড-বেস জুড়ে ক্লিনআপ কোড (বা ক্লিনআপ অবশ্যই ঘটবে) এর সদৃশ হ'ল "সংক্ষিপ্ত" এবং "সহজেই পঠনযোগ্য"? RAII সহ, আপনি এই জাতীয় কোডটি একবার লিখেছিলেন এবং এটি স্বয়ংক্রিয়ভাবে সর্বত্র প্রয়োগ করা হবে।
মানকারসে

55

থেকে কেন সি প্রদান ++ না একটি "পরিশেষে" গঠন করা? মধ্যে বিয়ারনে স্ট্রোভস্ট্রুপের এর সি ++ স্টাইল এবং টেকনিক প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী :

কারণ সি ++ এমন বিকল্পকে সমর্থন করে যা প্রায় সর্বদা ভাল: "রিসোর্স অধিগ্রহণ ইনিশিয়ালাইজেশন" কৌশল (টিসি ++ পিএল 3 বিভাগ 14.4)। স্থানীয় ধারণাটি কোনও স্থানীয় অবজেক্টের মাধ্যমে কোনও উত্সকে উপস্থাপন করা হয়, যাতে স্থানীয় অবজেক্টের ডেস্ট্রাক্টর রিসোর্সটি প্রকাশ করে। এইভাবে, প্রোগ্রামার রিসোর্সটি প্রকাশ করতে ভুলতে পারে না।


5
তবে সেই কৌশল সম্পর্কে কিছুই নেই যা নির্দিষ্ট +++ এর সাথে নির্দিষ্ট, সেখানে কি আছে? আপনি অবজেক্ট, কনস্ট্রাক্টর এবং ডেস্ট্রাক্টর দিয়ে যে কোনও ভাষায় আরআইআই করতে পারেন। এটি একটি দুর্দান্ত কৌশল, তবে আরআইআইআই কেবল বিদ্যমান তা বোঝায় না যে স্ট্রসআপ যা বলছে তা সত্ত্বেও কোনও finallyনির্মাণ সর্বদা চিরকাল এবং সর্বদা অকেজো । "ব্যতিক্রমী নিরাপদ কোড" লেখার বিষয়টি কেবল সি ++ এ বড় চুক্তি তার প্রমাণ is হেক, সি # এর উভয়ই ডেস্ট্রাক্টর এবং এবং তারা উভয়ই ব্যবহৃত হয়। finally
ট্যাক্রয়

28
@Tacroy: সি ++ খুব কম মূলধারার ভাষা রয়েছে যে এক নির্ণায়ক destructors। সি # "ডেস্ট্রাক্টর" এই উদ্দেশ্যে অকেজো, এবং আপনাকে RAII থাকতে "ব্লক ব্যবহার করে" ম্যানুয়ালি লিখতে হবে।
নেমানজা ত্রিফুনোভিচ

15
@ মাইকী আপনার কাছে উত্তর রয়েছে যে "সি ++ একটি" অবশেষে "নির্মাণ কেন সরবরাহ করে না?" সরাসরি স্ট্রস্ট্রস্ট্র থেকেই সেখানে there আপনি আর কি চাইতে পারেন? যে হয় কেন।

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

19
@ কাজ: আমার কেবল একবার ডিস্ট্রাক্টরে পরিষ্কার করার কথা মনে রাখা দরকার এবং তার পর থেকে আমি কেবলমাত্র এটিটি ব্যবহার করব। আমি বরাদ্দ হওয়া অপারেশনটি যতবার ব্যবহার করি না কেন অবশেষে ব্লকটিতে পরিষ্কার করা আমার মনে রাখা দরকার।
ডিফোর্ড

19

সি ++ না থাকার কারণটি এটি সি ++ তে প্রয়োজন নেই finallyfinallyকিছু ব্যতিক্রম ঘটেছে কিনা তা নির্বিশেষে কিছু কোড কার্যকর করতে ব্যবহৃত হয় যা প্রায় সবসময়ই এক ধরণের ক্লিনআপ কোড is সি ++-তে, এই ক্লিনআপ কোডটি প্রাসঙ্গিক শ্রেণীর ডেস্ট্রাক্টরের মধ্যে থাকা উচিত এবং ডাস্ট্রাক্টরকে সর্বদা ডাকা হবে, ঠিক যেমন একটি finallyব্লকের মতো । আপনার ক্লিনআপের জন্য ডেস্ট্রাক্টর ব্যবহার করার প্রতিমাটিকে RAII বলা হয় ।

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

সি ++ সম্প্রদায়ে ব্যতিক্রম সুরক্ষার বিষয়ে আরও বেশি আলোচনা হওয়ার কারণটি সম্ভবত সি ++ তে কী ভুল হতে পারে সে সম্পর্কে আপনাকে আরও সচেতন হতে হবে, কারণ ভাষাতে ডিফল্ট সুরক্ষা জাল কম রয়েছে।


2
দ্রষ্টব্য: দয়া করে দাবি করবেন না যে সি ++ এর ডিস্ট্রিমেন্টিক ডেস্ট্রাক্টর রয়েছে। অবজেক্ট পাস্কল / ডেল্ফিরও ডিস্ট্রিমেন্টিক ডেস্ট্রাক্টর রয়েছে তবুও 'শেষ পর্যন্ত' সমর্থন করে, খুব ভাল কারণে আমি নীচে আমার প্রথম মন্তব্যে ব্যাখ্যা করেছি।
ভেক্টর

13
@ মাইকি: finallyসি ++ স্ট্যান্ডার্ডে যুক্ত করার প্রস্তাব কখনও আসে নি বলে আমি মনে করি যে সি ++ সম্প্রদায় কোনও the absence of finallyসমস্যা মনে করে না এই সিদ্ধান্তটি নেওয়া নিরাপদ । বেশিরভাগ ভাষায় যেগুলি finallyসি ++ এর নিয়মিত ধ্বংসাত্মক ধ্বংসের অভাব রয়েছে। আমি দেখতে পাচ্ছি যে ডেলফির এ দুটোই আছে, তবে এর ইতিহাসটি আমি ভালভাবে জানি না যে সেখানে প্রথমে কোনটি ছিল know
বার্ট ভ্যান ইনজেন শেহেনো

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

2
সি ++ তে পুরো প্রচুর ক্রাফ্ট রয়েছে যা তর্কযোগ্যভাবে প্রয়োজন নেই, সুতরাং এটি সঠিক উত্তর হতে পারে না।
কাজ

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

12

অন্যরা সমাধান হিসাবে RAII নিয়ে আলোচনা করেছেন। এটি একটি পুরোপুরি ভাল সমাধান। তবে এটি কেন পুরোপুরি finallyকাঙ্ক্ষিত জিনিস যেহেতু তারা কেন যোগ করলেন না তা সত্যিই তা বিবেচনা করে না । এর উত্তর সি ++ এর নকশা এবং বিকাশের জন্য আরও মৌলিক: সি ++ এর বিকাশের পুরোপুরি জড়িতরা ডিজাইন বৈশিষ্ট্যগুলির প্রবর্তনকে দৃ strongly়ভাবে প্রতিহত করেছেন যা বিপুল পরিমাণে হট্টগোল ছাড়াই অন্যান্য বৈশিষ্ট্যগুলি ব্যবহার করে অর্জন করা যেতে পারে এবং বিশেষত যেখানে এটির প্রয়োজনের প্রয়োজন পুরানো কোডটি বেমানান হতে পারে এমন নতুন কীওয়ার্ডগুলির of যেহেতু RAII এর জন্য একটি অত্যন্ত কার্যকরী বিকল্প সরবরাহ করে finallyএবং আপনি বাস্তবে যে finallyকোনও উপায়ে সি ++ 11 এ নিজের রোল করতে পারেন , এর জন্য খুব কম কল ছিল।

আপনাকে যা করতে হবে তা হ'ল একটি ক্লাস তৈরি করা Finallyযা ফাংশনটিকে এটির ডিস্ট্রাক্টর এর কনস্ট্রাক্টরে পাস বলে। তারপরে আপনি এটি করতে পারেন:

try
{
    Finally atEnd([&] () { database.close(); });

    database.doRisky();
}

বেশিরভাগ নেটিভ সি ++ প্রোগ্রামাররা সাধারণত, পরিষ্কারভাবে ডিজাইন করা RAII অবজেক্টগুলিকে পছন্দ করবে।


3
আপনি আপনার ল্যাম্বডায় রেফারেন্স ক্যাপচার মিস করছেন। Finally atEnd([&] () { database.close(); });এছাড়াও হওয়া উচিত , আমি কল্পনা করি যে নিম্নলিখিতগুলি আরও ভাল: { Finally atEnd(...); try {...} catch(e) {...} }(আমি চেষ্টার বাইরে ফাইনালাইজারটি
তুলেছিলাম

2

আপনি "ট্র্যাপ" প্যাটার্ন ব্যবহার করতে পারেন - আপনি চেষ্টা / ক্যাচ ব্লক ব্যবহার করতে না চাইলেও।

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


1
এটি প্রশ্নের উত্তর দেয় না, এবং কেবল প্রমাণ করে যে অবশেষে এত খারাপ ধারণা নয় ...
ভেক্টর

2

ভাল, আপনি finallyল্যাম্বডাস ব্যবহার করে নিজের মতো করে নিজের মতো করে রোল করতে পারেন , যা জরিমানা সংকলনের জন্য নিম্নলিখিতটি পেতে পারে (অবশ্যই RAII ব্যতীত উদাহরণ ব্যবহার করে, কোডের সর্বোত্তম অংশ নয়):

{
    FILE *file = fopen("test","w");

    finally close_the_file([&]{
        cout << "We're closing the file in a pseudo-finally clause." << endl;
        fclose(file);
    });
}

এই নিবন্ধটি দেখুন ।


-2

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

এই জাতীয় কোড পাথ বিবেচনা করুন:

void foo() {
    try {
        ... stuff ...
        complex_cleanup();
    } catch (A& a) {
        handle_a(a);
        complex_cleanup();
        throw;
    } catch (B& b) {
        handle_b(b);
        complex_cleanup();
        throw;
    } catch (...) {
        handle_generic();
        complex_cleanup();
        throw;
    }
}

আমাদের থাকলে আমরা finallyলিখতে পারতাম:

void foo() {
    try {
        ... stuff ...
    } catch (A& a) {
        handle_a(a);
        throw;
    } catch (B& b) {
        handle_b(b);
        throw;
    } catch (...) {
        handle_generic();
        throw;
    } finally {
        complex_cleanup();
    }
}

তবে আরআইআইআই ব্যবহার করে সমতুল্য আচরণ পাওয়ার জন্য আমি খুঁজে পেতে পারি এমন কোনও উপায় নেই।

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


1
আপনার দ্বিতীয় উদাহরণে, যদি complex_cleanupফেলে দিতে পারে তবে আপনার ক্ষেত্রে এমন দুটি মামলা থাকতে পারে যেখানে একবারে দু'জন ব্যতিক্রম ব্যতিক্রম হয়, ঠিক যেমন আপনি RAII / ডেস্ট্রাক্টরদের সাথে করেন এবং সি ++ এটি অনুমতি দিতে অস্বীকার করে। আপনি যদি আসল ব্যতিক্রমটি দেখতে চান তবে তারপরে complex_cleanupকোনও ব্যতিক্রম যেমন রাইআইআই / ডেস্ট্রাক্টরদের সাথে করা উচিত তেমনি প্রতিরোধ করা উচিত। আপনি যদি complex_cleanupএর ব্যতিক্রম দেখতে চান তবে আমি মনে করি আপনি নেস্টেড ট্রাই / ক্যাচ ব্লক ব্যবহার করতে পারেন - যদিও এটি একটি স্পর্শকাতর এবং একটি মন্তব্যে ফিট করা শক্ত, সুতরাং এটি পৃথক প্রশ্নের পক্ষে মূল্যবান।
জোশ কেলি

আরও নিরাপদে প্রথম উদাহরণ হিসাবে অভিন্ন আচরণ পেতে আমি আরআইআইআই ব্যবহার করতে চাই। একটি পুটিক finallyব্লকের একটি ছোঁড়া স্পষ্টতই catchব্লক ডাব্লুআরটি-ইন-ফ্লাইট ব্যতিক্রমগুলিতে একটি ছোঁড়ার মতোই কাজ করবে - কল নয় std::terminate। প্রশ্নটি হল "কেন finallyসি ++ তে নেই?" এবং উত্তরগুলি সমস্ত বলে "আপনার এটির দরকার নেই ... RAII FTW!" আমার বক্তব্যটি হ্যাঁ, RAII মেমরি ম্যানেজমেন্টের মতো সহজ ক্ষেত্রে যেমন ঠিক আছে তবে ব্যতিক্রমগুলির বিষয়টি সমাধান না হওয়া পর্যন্ত এটি একটি সাধারণ-উদ্দেশ্য সমাধান হিসাবে খুব বেশি চিন্তাভাবনা / ওভারহেড / উদ্বেগ / পুনরায় নকশা প্রয়োজন।
ম্যাড সায়েন্টিস্ট

3
আমি আপনার বক্তব্যটি বুঝতে পারি - ধ্বংসকারীদের সাথে কিছু বৈধ সমস্যা রয়েছে যা ফেলে দিতে পারে - তবে সেগুলি বিরল। এই বলে যে RAII + ব্যতিক্রমগুলি অমীমাংসিত সমস্যা রয়েছে বা RAII কোনও সাধারণ-উদ্দেশ্য সমাধান সহজেই বেশিরভাগ সি ++ বিকাশকারীদের অভিজ্ঞতার সাথে মেলে না।
জোশ কেলি

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

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