সি ++ ক্লাস কনস্ট্রাক্টারে ব্যর্থতার কেসগুলি কীভাবে পরিচালনা করবেন?


21

আমার সিপিপি ক্লাস রয়েছে যার নির্মাতা কিছু অপারেশন করে। এর মধ্যে কয়েকটি অপারেশন ব্যর্থ হতে পারে। আমি জানি যে কনস্ট্রাক্টররা কিছু ফিরিয়ে দেয় না।

আমার প্রশ্নগুলি হ'ল,

  1. এটি কি অন্য কোনও অপারেশন করার অনুমতি দেয় যা কোনও কনস্ট্রাক্টরে সদস্যদের সূচনা করে?

  2. কলিং ফাংশনটি বলতে কি সম্ভব যে কনস্ট্রাক্টরের কিছু ক্রিয়াকলাপ ব্যর্থ হয়েছে?

  3. new ClassName()কনস্ট্রাক্টরে কিছু ত্রুটি দেখা দিলে আমি কি রিটার্ন নুল করতে পারি ?


22
আপনি কনস্ট্রাক্টর থেকে একটি ব্যতিক্রম নিক্ষেপ করতে পারেন। এটি সম্পূর্ণ বৈধ প্যাটার্ন।
অ্যান্ডি

1
আপনি সম্ভবত জিওএফ-এর কিছু সৃষ্টিশীল নিদর্শন দেখে নিন । আমি ফ্যাক্টরি প্যাটার্ন সুপারিশ।
স্পেসট্রকার

2
# 1 এর একটি সাধারণ উদাহরণ হ'ল ডেটা বৈধতা। আইই, যদি আপনার কোনও ক্লাস থাকে Square, এমন একটি কনস্ট্রাক্টরের সাথে একটি প্যারামিটার লাগে, একটি দিকের দৈর্ঘ্য, আপনি মানটি 0 এর চেয়ে বেশি কিনা তা পরীক্ষা করে দেখতে চান
ডেভিড মনিকা

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

1
# 3 - কেন আপনি একটি নল ফেরত চান? ওওর অন্যতম সুবিধা হ'ল রিটার্নের মানগুলি পরীক্ষা করা উচিত নয়। যথাযথ সম্ভাব্য ব্যতিক্রমগুলি কেবল ধরা ()।
মিঃ ওয়ান্ডারফুল

উত্তর:


42
  1. হ্যাঁ, যদিও কিছু কোডিং মান এটি নিষিদ্ধ করতে পারে।

  2. হ্যাঁ। প্রস্তাবিত উপায় হ'ল ব্যতিক্রম ছোঁড়া। বিকল্পভাবে, আপনি বস্তুর ভিতরে ত্রুটি সম্পর্কিত তথ্য সংরক্ষণ করতে পারেন এবং এই তথ্য অ্যাক্সেসের জন্য পদ্ধতি সরবরাহ করতে পারেন।

  3. না।


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

@ ডেভিডপ্যাকার সম্মত হয়েছেন, এখানে দেখুন: stackoverflow.com/questions/77639/… তবে কিছু কোডিং নির্দেশিকা ব্যতিক্রমগুলি নিষিদ্ধ করে, যা নির্মাণকারীদের জন্য সমস্যাযুক্ত।
সেবাস্তিয়ান রেডল

কোনওভাবেই আমি ইতিমধ্যে আপনাকে উত্তরটির জন্য একটি প্রস্তাব দিয়েছি, সেবাস্তিয়ান। মজাদার. : ডি
অ্যান্ডি

10
@ooxi না, তা নয়। আপনার ওভাররাইড হওয়া নতুনকে মেমোরি বরাদ্দের জন্য ডাকা হয়, তবে আপনার অপারেটর ফিরে আসার পরে কন্ট্রাক্টরের কাছে কলটি করা হয় যার অর্থ আপনি ত্রুটিটি ধরতে পারবেন না। এটা ধরে নিই যে নতুন বলা হয়; এটি স্ট্যাক-বরাদ্দ হওয়া সামগ্রীর জন্য নয়, যা তাদের বেশিরভাগের হওয়া উচিত।
সেবাস্তিয়ান রেডল

1
# 1 এর জন্য, আরআইআই একটি সাধারণ উদাহরণ যেখানে কনস্ট্রাক্টরে আরও বেশি কাজ করার প্রয়োজন হতে পারে।
এরিক

20

আপনি একটি স্থিতিশীল পদ্ধতি তৈরি করতে পারেন যা গণনা সম্পাদন করে এবং সাফল্যের ক্ষেত্রে কোনও বস্তু ফেরত দেয় অথবা ব্যর্থতার ক্ষেত্রে নয়।

অবজেক্টের এই নির্মাণটি কীভাবে করা হচ্ছে তার উপর নির্ভর করে অন্য কোনও অবজেক্ট তৈরি করা ভাল যা একটি অ স্থিত পদ্ধতিতে অবজেক্ট তৈরির অনুমতি দেয়।

কনস্ট্রাক্টরকে অপ্রত্যক্ষভাবে কল করা প্রায়শই "কারখানা" হিসাবে পরিচিত।

এটি আপনাকে কোনও নাল-অবজেক্ট ফেরত দেওয়ারও অনুমতি দেয়, এটি নাল ফেরার চেয়ে ভাল সমাধান হতে পারে।


আপনাকে ধন্যবাদ @ নাল! দুর্ভাগ্যক্রমে এখানে দুটি উত্তর গ্রহণ করতে পারবেন না :( অন্যথায় আমিও এই উত্তরটি গ্রহণ করতাম !! ধন্যবাদ আবার!
ময়ূরক

কোন উদ্বেগ @MayurK, গৃহীত উত্তর চিহ্নিত করতে নয় সঠিক উত্তর, কিন্তু এক যে আপনার জন্য কাজ করেন।
নাল

3
@ নুল: সি ++ এ আপনি কেবল ফিরে আসতে পারবেন না NULL। উদাহরণস্বরূপ, int foo() { return NULLআপনি আসলে ফিরে আসবেন 0(শূন্য), একটি পূর্ণসংখ্যার অবজেক্ট। ইন std::string foo() { return NULL; }আপনি দূর্ঘটনাক্রমে কল চাই std::string::string((const char*)NULL)যা অনির্দিষ্ট আচরণ (নাল একটি \ 0-সমাপ্ত স্ট্রিং নির্দেশ করে না)।
MSalters

3
std :: alচ্ছিক উপায় দূরে হতে পারে তবে আপনি সর্বদা বুস্ট :: alচ্ছিক ব্যবহার করতে পারেন যদি আপনি সেই পথে যেতে চান।
শান বার্টন

1
@ ভোল্ড: সি ++ তে অবজেক্টগুলি শ্রেণির ধরণের মধ্যে সীমাবদ্ধ নয়। আর জেনেরিক প্রোগ্রামিং সঙ্গে, তাই না বিরল জন্য কারখানা দিয়ে শেষ করতে int। যেমন std::allocator<int>একটি পুরোপুরি বুদ্ধিমান কারখানা।
MSalters

5

@ সেবাস্তিয়ানআরডেল ইতিমধ্যে সহজ, সরাসরি উত্তর দিয়েছেন, তবে কিছু অতিরিক্ত ব্যাখ্যা কার্যকর হতে পারে।

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


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

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

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

যদি কনস্ট্রাক্টরের অভ্যন্তরে কোনও ব্যতিক্রম নিক্ষেপ ঘটে, তবে অংশ-নির্মিত কোনও কিছু পরিষ্কারভাবে পরিষ্কার করা দরকার, সাধারণত একটিতে try .. catch

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

classname (args) : base1 (args), member2 (args), member3 (args)
{
}

এই নির্মাতার শরীর খালি। তাই দীর্ঘ জন্য কনস্ট্রাকটর base1, member2এবং member3ব্যতিক্রম নিরাপদ, সেখানে চিন্তার কিছু নেই আছে। উদাহরণস্বরূপ, যদি কনস্ট্রাক্টর member2নিক্ষেপ করে তবে সেই কনস্ট্রাক্টর নিজেকে পরিষ্কার করার জন্য দায়বদ্ধ। বেসটি base1ইতিমধ্যে সম্পূর্ণরূপে নির্মিত হয়েছিল, তাই এর ধ্বংসকারীকে স্বয়ংক্রিয়ভাবে কল করা হবে। member3এমনকি আংশিকভাবে কখনও নির্মিত হয়নি, তাই পরিষ্কার করার দরকার নেই।

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

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

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


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

সুতরাং, "কর-সর্বনিম্ন" কন্সট্রাক্টর ব্যক্তিগত হতে পারে এবং "মেক_উইল ওয়েল ()" ফাংশনটি অন্য নির্মাণকারী হতে পারে যা ব্যক্তিগতকে ডাকে।
বেন ভয়েগট

এটি আমার সাথে পরিচিত আরএআইআইয়ের সংজ্ঞা নয়। RAII সম্পর্কে আমার বোঝা হ'ল কোনও অবজেক্টের কনস্ট্রাক্টরে (এবং কেবলমাত্র) ইচ্ছাকৃতভাবে একটি সংস্থান অর্জন করা এবং এটি তার ডিস্ট্রাক্টরটিতে ছেড়ে দেওয়া। এই উপায়ে স্ট্যাকের মধ্যে অবজেক্টটি স্বয়ংক্রিয়ভাবে অধিগ্রহণ এবং এটি এনপ্যাপুলেট করা সংস্থানগুলি রিলিজ করার জন্য ব্যবহার করা যেতে পারে। ক্লাসিক উদাহরণটি এমন একটি লক যা নির্মাণের সময় একটি মুটেক্স অর্জন করে এবং ধ্বংসের সময় ছেড়ে দেয়।
এরিক

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

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