স্ট্যান্ড :: ব্যতিক্রম থেকে একজনের প্রাপ্ত / উত্তরাধিকারী হওয়া উচিত?


15

আমার প্রথম 'সিরিয়াস' সি ++ লাইব্রেরি ডিজাইন করার সময়, আমি নিজেকে জিজ্ঞাসা করছি:

এর থেকে ব্যতিক্রম std::exceptionএবং এটি অফস্প্রিংগুলি অর্জন করা কি ভাল স্টাইল ?!

পড়ার পরেও

আমি এখনও নিশ্চিত নই। কারণ, প্রচলিত (তবে সম্ভবত ভাল না) অনুশীলনের পাশাপাশি, আমি ধরে নেব, একটি গ্রন্থাগার ব্যবহারকারী হিসাবে, একটি গ্রন্থাগার ফাংশন std::exceptionকেবল তখনই ছুঁড়ে ফেলা হয় যখন গ্রন্থাগার বাস্তবায়নে স্ট্যান্ডার্ড লাইব্রেরি ফাংশন ব্যর্থ হয়, এবং এটি এ সম্পর্কে কিছুই করতে পারে না। তবে তবুও, অ্যাপ্লিকেশন কোডটি লেখার সময়, আমার জন্য এটি খুব সুবিধাজনক এবং আইএমএইচওও কেবল একটি নিক্ষেপ করতে ভাল লাগছে std::runtime_error। এছাড়াও আমার ব্যবহারকারীরাও নির্ধারিত সর্বনিম্ন ইন্টারফেসের মতো what()বা কোডগুলিতে নির্ভর করতে পারেন ।

এবং উদাহরণস্বরূপ, আমার ব্যবহারকারী ত্রুটিযুক্ত যুক্তি সরবরাহ করে, একটি নিক্ষেপ করার চেয়ে আরও সুবিধাজনক আর কী হবে std::invalid_argument, তাই না? সুতরাং স্ট্যান্ড :: ব্যতিক্রমের এখনও সাধারণ ব্যবহারের সাথে আমি অন্যের কোড দেখতে পাচ্ছি: কেন আরও এগিয়ে যান এবং আপনার কাস্টম ব্যতিক্রম শ্রেণি (যেমন: lib_foo_exception) এবং এর থেকে নেওয়া হয় না std::exception

থটস?


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

3
পার্থক্যটি হ'ল, যখন আমার lib_foo_exceptionক্লাসটি এসেছে std::exception, গ্রন্থাগার ব্যবহারকারী কেবল ধরা lib_foo_exceptionদিয়ে ধরবে std::exception, এছাড়াও যখন তিনি কেবল লিবারি ধরেন। সুতরাং আমি জিজ্ঞাসা করতে পারি আমার লাইব্রেরি ব্যতিক্রমের মূল শ্রেণিটি স্ট্যান্ড :: ব্যতিক্রম থেকে উত্তরাধিকার সূত্রে প্রাপ্ত ?
সুপারলোক্কাস

3
@ লাইটনেসেসেসিনআরবিট মানে "... ..." ছাড়াও "ধরার কত উপায় আছে lib_foo_exception?" থেকে inheriting সঙ্গে std::exceptionআপনি এটা করে করতে পারেন catch(std::exception)বা দ্বারা catch(lib_foo_exception)। থেকে প্রাপ্ত না করে std::exception, আপনি এটি যদি কেবল এবং কেবল যদি , দ্বারা ধরতেন catch(lib_foo_exception)
সুপারলোককাস

2
@ সুপারলক্কাস: আমরা এড়িয়ে চলেছি catch(...)। এটি সেখানে রয়েছে কারণ ভাষাটি বিবেচনার ক্ষেত্রে (এবং "দুর্ব্যবহার" গ্রন্থাগারগুলির জন্য) অনুমতি দেয় তবে এটি আধুনিক সেরা অনুশীলন নয়।
মনিকা

1
সি ++ এ ব্যতিক্রম হ্যান্ডলিংয়ের অনেকগুলি নকশা মোটা, আরও সাধারণ catchসাইট এবং একইভাবে মোটা লেনদেনকে উত্সাহিত করে যা ব্যবহারকারীর সমাপ্তির ক্রিয়াকলাপ model যদি আপনি এটিকে এমন ভাষাগুলির সাথে তুলনা করেন যা সাধারণ ধরার ধারণাটিকে উত্সাহ দেয় না std::exception&, উদাহরণস্বরূপ, তাদের প্রায়শই try/catchখুব নির্দিষ্ট ত্রুটিযুক্ত মধ্যস্থতাকারী ব্লকের সাথে অনেক বেশি কোড থাকে , যা ব্যতিক্রমী-হ্যান্ডলিংয়ের সাধারণতা কিছুটা কমিয়ে দেয় শুরু হওয়ার সাথে সাথে exception ম্যানুয়াল ত্রুটি পরিচালনার উপর এবং সম্ভবত যে সমস্ত পৃথক ত্রুটি ঘটতে পারে তার উপর অনেক বেশি জোর দেওয়া।

উত্তর:


29

সমস্ত ব্যতিক্রম থেকে উত্তরাধিকারী হওয়া উচিত std::exception

ধরুন, উদাহরণস্বরূপ, আমাকে কল করা দরকার ComplexOperationThatCouldFailABunchOfWays(), এবং এটি যে কোনও ব্যতিক্রম ছুঁড়ে ফেলতে পারে তা আমি পরিচালনা করতে চাই। যদি সমস্ত কিছুই উত্তরাধিকার সূত্রে প্রাপ্ত হয় std::exceptionতবে এটি সহজ। আমার কেবলমাত্র একটি একক catchব্লক প্রয়োজন , এবং what()বিশদ পাওয়ার জন্য আমার একটি স্ট্যান্ডার্ড ইন্টারফেস ( ) রয়েছে।

try {
    ComplexOperationThatCouldFailABunchOfWays();
} catch (std::exception& e) {
    cerr << e.what() << endl;
}

যদি ব্যতিক্রমগুলি উত্তরাধিকার সূত্রে না std::exceptionপায় তবে এটি অনেক কৃপণ হয়:

try {
    ComplexOperationThatCouldFailABunchOfWays();
} catch (std::exception& e) {
    cerr << e.what() << endl;
} catch (Exception& e) {
    cerr << e.Message << endl;
} catch (framework_exception& e) {
    cerr << e.Details() << endl;
}

আপনার নিজের সাবক্ল্যাস নিক্ষেপ করার জন্য তৈরি করা runtime_errorবা invalid_argumentবনাম তৈরি করার বিষয়ে std::exception: আমার থাম্বের নিয়মটি হল যখনই আমি অন্য ত্রুটিগুলির তুলনায় নির্দিষ্ট ধরণের ত্রুটিটি হ্যান্ডেল করার প্রয়োজন হয় (যেমন যখনই আমার আলাদা catchব্লকের প্রয়োজন হয়) তখন একটি নতুন সাবক্লাস প্রবর্তন করা ।

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

সি ++ কোর নির্দেশিকা আরও আলোচনা এবং উদাহরণ আছে।


ওসব এম্পারস্যান্ড! সি ++ অদ্ভুত।
সুপারজেডি ২৪

2
@ সুপারজেডি ২২৪ এবং এই সমস্ত ভিন্ন চিঠি! ইংরাজী অদ্ভুত।
জোহানেস

এই যুক্তিটি আমার কাছে বোঝায় না। এটি কি catch (...)(আক্ষরিক উপবৃত্ত সহ) জন্য নয়?
ম্যাক্সপাম

1
@ ম্যাক্সএমপি catch (...)কেবল তখনই কার্যকর যখন আপনার নিক্ষেপ করা কিছুর সাথে কিছু করার দরকার নেই । আপনি যদি কিছু করতে চান - যেমন, উদাহরণ হিসাবে নির্দিষ্ট ত্রুটি বার্তাটি প্রদর্শন করুন বা লগ করুন, যেমন আমার উদাহরণ হিসাবে - তবে আপনাকে এটি জানতে হবে।
জোশ কেলি

9

আমি ধরে নেব, একটি লাইব্রেরি ব্যবহারকারী হিসাবে, একটি গ্রন্থাগার ফাংশন স্ট্যান্ড :: ব্যতিক্রম কেবল তখনই পাঠানো হবে যখন গ্রন্থাগার বাস্তবায়নে স্ট্যান্ডার্ড লাইব্রেরি ফাংশন ব্যর্থ হয় এবং এটি এ সম্পর্কে কিছুই করতে পারে না

এটি একটি ভুল ধারণা।

স্ট্যান্ডার্ড ব্যতিক্রম ধরণের "সাধারণ" ব্যবহারের জন্য সরবরাহ করা হয়। এগুলি কেবল স্ট্যান্ডার্ড লাইব্রেরি দ্বারা ব্যবহারের জন্য ডিজাইন করা হয়নি ।

হ্যাঁ, শেষ পর্যন্ত সবকিছুকে উত্তরাধিকার সূত্রে তৈরি করুন std::exception। প্রায়শই, যা থেকে std::runtime_errorবা উত্তরাধিকার সূত্রে জড়িত থাকে std::logic_error। আপনি প্রয়োগ করছেন এমন ব্যতিক্রম শ্রেণীর জন্য যা কিছু উপযুক্ত।

এটি অবশ্যই সাবজেক্টিভ - বেশ কয়েকটি জনপ্রিয় গ্রন্থাগার মানক গ্রন্থাগার থেকে গ্রন্থাগারগুলি ডিকুয়াল করার জন্য সম্ভবত স্ট্যান্ডার্ড ব্যতিক্রম প্রকারগুলি পুরোপুরি উপেক্ষা করে। ব্যক্তিগতভাবে আমি মনে করি এটি অত্যন্ত স্বার্থপর! এটি ব্যতিক্রম ধরা দেয় যে ডান পেতে আরও অনেক বেশি কঠিন।

ব্যক্তিগতভাবে কথা বলতে বলতে, আমি প্রায়শই কেবল একটি নিক্ষেপ করি std::runtime_errorএবং এটি দিয়ে হয়ে যাই । কিন্তু এটি কীভাবে আপনার ব্যতিক্রম ক্লাসগুলি কীভাবে দান করা উচিত তা নিয়ে আলোচনার মধ্যে চলেছে যা আপনি যা জিজ্ঞাসা করছেন তা নয়।

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