- 1. Инварианты
- 2. Ерекшеліктер түрлері
- 3. std::logic_error
- 4. std::жарамсыз_аргумент
- 5. std::domain_error
- 6. std::length_қате
- 7. std::ауқымнан_ тыс
- 8. std::future_error
- 9. std::runtime_error
- 10. std::range_error
- 11. std::overflow_error
- 12. std::underflow_error
- 13. std::system_error
- 14. std::ios_base::сәтсіздік
- 15. std::bad_typeid
- 16. std::bad_cast
- 17. std::bad_weak_ptr
- 18. std::жаман_функция_шақыруы
- 19. std::bad_alloc
- 20. std::жаман_массив_жаңа_ұзындық
- 21. std::bad_ерекшелік
Ерекшелік дегеніміз не? Бұл бағдарламаның стандартты тәртібімен қамтамасыз етілмеген жағдай. Мысалы, Вектор сыныбында жоқ элементке қол жеткізу әрекеті (біз оны сыныптар мақаласында талқылағанбыз). Яғни, вектор шектен тыс. Бұл жағдайда бағдарламаның орындалуын үзу үшін ерекше жағдайларды пайдалануға болады. Бұл қажет, өйткені
- Әдетте, мұндай жағдайларда Вектор класының авторы пайдаланушы өз класын қалай пайдаланғысы келетінін білмейді, сонымен қатар бұл класс қандай бағдарламада қолданылатынын білмейді.
- Вектор класының пайдаланушысы бұл класстың дұрыс жұмысын әрқашан бақылай алмайды, сондықтан оған бірдеңе дұрыс болмады деп хабарлау қажет.
C++ тілінде мұндай жағдайларды шешу үшін ерекшеліктер техникасын қолдануға болады.
Vector класында жоқ индекс бойынша элементке қол жеткізу әрекеті болған жағдайда ерекше жағдайды қалай жазу керектігін қарастырайық.
double& Vector::operator[](int i) { if (i<0 || size()<=i) throw out_of_range{"Vector::operator[]"}; return elem[i]; }
ауқымнан_ тыс ерекше жағдай осы жерде қолданылады.
Бұл ерекшелік тақырып файлында анықталған
throw операторы басқаруды Vector::operator функциясын тікелей немесе жанама түрде шақыратын кейбір функциядағы ауқымнан_ тыс түріндегі ерекше жағдай өңдеушісіне береді. Ерекшеліктерді өңдеу үшін мәлімдемелер блогын пайдалану керек catch көріңіз.
void f(Vector& v) { // ... try { // блок обработки функции с исключением v[v.size()] = 7; // попытка доступа к элементу за пределами вектора } catch (out_of_range) { // ловим ошибку out_of_range // ... обработки ошибки out_of_range ... } // ... }
Инварианты
Сондай-ақ, try catch блоктары C++ ерекшелік механизмінің жұмысына инварианттылықты енгізетін бірнеше түрлі ерекшеліктерді өңдеуге мүмкіндік береді.
Мысалы, вектор класы жасалған кезде вектордың қате өлшемін алуы немесе құрамында болатын элементтер үшін бос жад таба алмауы мүмкін.
Vector::Vector(int s) { if (s < 0) throw length_error{}; elem = new double[s]; sz = s; }
Бұл конструктор екі жағдайда ерекшелік жасай алады:
- өлшем аргументі ретінде теріс мән берілсе
- new операторы жадты бөле алмаса
length_error стандартты ерекшелік операторы болып табылады, өйткені std кітапханасы өз жұмысында осы ерекшеліктерді жиі пайдаланады.
Ерекше жағдайды өңдеу келесідей болады:
void test() { try { Vector v(−27); } catch (std::length_error) { // обработка отрицательного размера вектора } catch (std::bad_alloc) { // обработка ошибки выделения памяти } }
Сіз сондай-ақ өзіңіздің ерекше жағдайларыңызды бөлектей аласыз.
Ерекшеліктер түрлері
Барлық стандартты кітапхана ерекшеліктер std::exception. мұрағатынан алынады.
Қазіргі уақытта ерекше жағдайлардың келесі түрлері бар:
- логикалық_қате
- жарамсыз_аргумент
- домен_қатесі
- ұзындық_қателігі
- диапазоннан_ тыс
- болашақ_қате (C++11)
- орындау уақыты_қателігі
- ауқым_қателігі
- толып кету_қателігі
- астыңғы_қате
- жүйелік_қате (C++11)
- ios_base::сәтсіздік (C++11-ден бастап)
- нашар_түрі
- нашар_cast
- bad_weak_ptr (C++11)
- нашар_функция_шақыруы (C++11)
- нашар_бөлу
- bad_array_new_length (C++11)
- нашар_ерекшелік
- ios_base :: сәтсіздік (C++ 11 дейін)
std::logic_error
Тақырып файлында анықталған ерекше жағдай
Ерекшелік ретінде лақтырылатын нысан түрін көрсетеді. Ол логикалық алғышарттың немесе алдын алуға болатын инварианттар класының бұзылуы сияқты бағдарламадағы дұрыс емес логиканың нәтижесі болып табылатын қателер туралы хабарлайды.
Бұл сынып тек орындау уақытында анықталатын қателер үшін негіз ретінде пайдаланылады.
std::жарамсыз_аргумент
Тақырып файлында анықталған ерекше жағдай
std::logic_error ішінен мұраланған. Жарамсыз аргумент болған жағдайда шығарылатын ерекше жағдайды анықтайды.
Мысалы, MSDN стандартты кітапханадан биттер класының объектісі болған кезде мысал береді
// invalid_arg.cpp // compile with: /EHsc /GR #include <bitset> #include <iostream> using namespace std; int main( ) { try { bitset< 32 > bitset( string( "11001010101100001b100101010110000") ); } catch ( exception &e ) { cerr << "Caught " << e.what( ) << endl; cerr << "Type " << typeid( e ).name( ) << endl; }; } \* Output: Caught invalid bitset<N> char Type class std::invalid_argument *\
Бұл мысалда жарамсыз жол жіберілді, оның ішінде қате болатын «b» таңбасы бар.
std::domain_error
Тақырып файлында анықталған ерекше жағдай
std::logic_error ішінен мұраланған. Берілген аргумент үшін математикалық функция анықталмаған жағдайда шығарылатын ерекше жағдайды көрсетеді, мысалы:
std::sqrt(-1)
std::length_қате
Тақырып файлында анықталған ерекше жағдай
std::logic_error ішінен мұраланған. Нысан үшін шектен тыс әрекетті орындау әрекеті жасалған кезде шығарылуы керек ерекше жағдайды көрсетеді. Мақаланың басындағы вектордың өлшемі үшін көрсетілгендей.
std::ауқымнан_ тыс
Тақырып файлында анықталған ерекше жағдай
std::logic_error ішінен мұраланған. Нысанның мәндер ауқымы шектен шыққан кезде шығарылатын ерекше жағдайды көрсетеді. Мақаланың басында вектор мәндерінің диапазоны үшін көрсетілгендей.
std::future_error
Тақырып файлында анықталған ерекше жағдай
std::logic_error ішінен мұраланған. Асинхронды режимде жұмыс істейтін және ағындар кітапханасына тәуелді функция орындалмаса, бұл ерекшелік жойылуы мүмкін. Бұл ерекшелік std::error_code параметрімен үйлесімді қате кодын қамтиды.
std::runtime_error
Тақырып файлында анықталған ерекше жағдай
Оңай болжау мүмкін емес және орындалу уақытында шығарылуы керек ерекше жағдайлардың негізгі ерекшелігі болып табылады.
std::range_error
Тақырып файлында анықталған ерекше жағдай
Ерекшелік өзгермелі нүкте мәндерін есептеудегі қателер үшін пайдаланылады, компьютер мәнді өңдей алмаса, себебі ол тым үлкен немесе тым кішкентай. Егер мән интегралдық мән болса, underflow_error немесе overflow_error ерекше жағдайларды пайдалану керек.
std::overflow_error
Тақырып файлында анықталған ерекше жағдай
Ерекшелік интегралдық түрдегі өзгермелі нүкте мәндерін есептеудегі қателер үшін пайдаланылады, санның тым үлкен оң мәні, оң шексіздігі бар, дәлдік жоғалады, яғни. нәтиже соншалықты үлкен, оны IEEE754 нөмірі ретінде көрсету мүмкін емес.
std::underflow_error
Тақырып файлында анықталған ерекше жағдай
Ерекшелік интегралдық түрдегі өзгермелі нүкте мәндерін есептеудегі қателер үшін қолданылады, онда дәлдік жоғалады, яғни. нәтиже соншалықты кішкентай, оны IEEE754 нөмірі ретінде көрсету мүмкін емес.
std::system_error
Тақырып файлында анықталған ерекше жағдай
std::system_error – әртүрлі стандартты кітапхана функциялары (әдетте std::thread конструкторы сияқты операциялық жүйемен әрекеттесетін функциялар) шығаратын ерекшелік түрі. сәйкес * std::error_code * .
std::ios_base::сәтсіздік
Тақырып файлында анықталған ерекше жағдай
Енгізу/шығару функциялары сәтсіз болғанда шығарылатын ерекше жағдайларға жауапты.
std::bad_typeid
Тақырып файлында анықталған ерекше жағдай
Бұл түрдегі ерекшелік typeid операторы полиморфты түрдегі нөлдік көрсеткішке қолданылғанда шығарылады.
#include <iostream> #include <typeinfo> struct S { // Тип должен быть полиморфным virtual void f(); }; int main() { S* p = nullptr; try { std::cout << typeid(*p).name() << '\n'; } catch(const std::bad_typeid& e) { std::cout << e.what() << '\n'; } }
std::bad_cast
Тақырып файлында анықталған ерекше жағдай
Бұл ерекше жағдай нысанды мұрагерлік қатынасы жоқ нысан түріне шығару әрекеті жасалғанда орын алады.
#include <iostream> #include <typeinfo> struct Foo { virtual ~Foo() {} }; struct Bar { virtual ~Bar() {} }; int main() { Bar b; try { Foo& f = dynamic_cast<Foo&>(b); } catch(const std::bad_cast& e) { std::cout << e.what() << '\n'; } }
std::bad_weak_ptr
Тақырып файлында анықталған ерекше жағдай
std::bad_weak_ptr – std::weak_ptr сілтейтін кезде std::weak_ptr аргумент ретінде қабылдайтын std::shared_ptr конструкторлары ерекшелік ретінде шығарған нысан түрі. әлдеқашан жойылған нысан.
#include <memory> #include <iostream> int main() { std::shared_ptr<int> p1(new int(42)); std::weak_ptr<int> wp(p1); p1.reset(); try { std::shared_ptr<int> p2(wp); } catch(const std::bad_weak_ptr& e) { std::cout << e.what() << '\n'; } }
std::жаман_функция_шақыруы
Тақырып файлында анықталған ерекше жағдай
Бұл ерекшелік std::function нысанының std::function::operator() әдісі шақырылып, функция нысанын алмаса, яғни ол nullptr ретінде жіберілген болса шығарылады. мысалы, инициализатор және функция нысаны ешқашан жіберілмеді.
#include <iostream> #include <functional> int main() { std::function<int()> f = nullptr; try { f(); } catch(const std::bad_function_call& e) { std::cout << e.what() << '\n'; } }
std::bad_alloc
Тақырып файлында анықталған ерекше жағдай
Жадты бөлу мүмкін болмаған кезде шақырылады.
std::жаман_массив_жаңа_ұзындық
Тақырып файлында анықталған ерекше жағдай
Ерекшелік келесі жағдайларда шығарылады:
- Жиым теріс өлшемге ие
- Жаңа массивтің жалпы өлшемі іске асыру арқылы анықталған ең үлкен мәннен асты
- Баптандыру элементтерінің саны баптандыру элементтерінің ұсынылған санынан асып түседі
#include <iostream> #include <new> #include <climits> int main() { int negative = -1; int small = 1; int large = INT_MAX; try { new int[negative]; // negative size new int[small]{1,2,3}; // too many initializers new int[large][1000000]; // too large } catch(const std::bad_array_new_length &e) { std::cout << e.what() << '\n'; } }
std::bad_ерекшелік
Тақырып файлында анықталған ерекше жағдай
std::bad_exception - келесі жағдайларда шығарылатын C++ ерекшелік түрі:
- Динамикалық ерекшелік спецификациясы бұзылса
- Егер std::exception_ptr ұсталған ерекше жағдайдың көшірмесін ұстаса және ерекше жағдай нысанының көшіру конструкторы current_exception ұстаған болса, онда ұсталған ерекше жағдай тасталады.
#include <iostream> #include <exception> #include <stdexcept> void my_unexp() { throw; } void test() throw(std::bad_exception) { throw std::runtime_error("test"); } int main() { std::set_unexpected(my_unexp); try { test(); } catch(const std::bad_exception& e) { std::cerr << "Caught " << e.what() << '\n'; } }
std::underflow_error - это не "число имеет слишком большое отрицательное значение", а потеря точности при вычислениях, т.е. результат настолько мал, что не может быть представлен числом в формате IEEE754
Спасибо. Дополнил.