最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一篇文章帶你了解C++中的異常

 更新時(shí)間:2022年02月23日 10:58:52   作者:是小明同學(xué)啊  
這篇文章主要為大家詳細(xì)介紹了C++中的異常,使用數(shù)據(jù)庫(kù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

異常

在c語(yǔ)言中,對(duì)錯(cuò)誤的處理總是兩種方法:

1,使用整型的返回值表示錯(cuò)誤(有時(shí)候用1表示正確,0表示錯(cuò)誤;有的時(shí)候0表示正確,1表示錯(cuò)誤)

2,使用errno宏(可以簡(jiǎn)單理解為一個(gè)全局整形變量)去記錄錯(cuò)誤。(如果錯(cuò)誤,就將被改變的全局整形變量返回)

c++中仍然可以用上面的兩種方法,但是有缺點(diǎn)。

(1)返回值不統(tǒng)一,到底是1表示正確,還是0表示正確。

(2)返回值只有一個(gè),通過函數(shù)的返回值表示錯(cuò)誤代碼,那么函數(shù)就不能返回其他的值。(輸出的值到底是表示異常的值-1,還是最后在那個(gè)結(jié)果就是-1呢)

拋出異常基本操作

c++處理異常的優(yōu)點(diǎn):

異常處理可以帶調(diào)用跳級(jí)。

img

在C程序中出現(xiàn)了異常,返回值為-1。如果C直接將-1傳給B,不進(jìn)行處理(也不給B報(bào)錯(cuò)),那么B收到-1返回值以后就會(huì)進(jìn)行自己的處理,然后返回給A,然后A再進(jìn)行自己的處理,那么最終程序返回的值肯定是錯(cuò)誤的。

所以在c++中,要求必須要處理異常。如果C處理不了允許拋給B處理,B處理不了也允許拋給A處理,如果A也處理不了,那么就直接終止代碼報(bào)錯(cuò)。

int myDivision(int a, int b)
{
	if (b == 0)
	{
		throw -1;//拋出-1
	}
	else
		return 1;
}
int main()
{
	int a = 10;
	int b = 0;
	try 
	{
		myDivision(a, b);
	}
	catch (int)
	{
		cout << "int類型異常捕獲" << endl;
	}
	return 0;
}

如果拋出來(lái)的是char類型的數(shù)據(jù)(異常),那么就需要有個(gè)char類型的接收處理代碼(catch+類型)。

除了int,char,double以外的拋出類型,可以用...來(lái)接收。

catch (...)
	{
		cout << "其他類型異常捕獲" << endl;
	}

如果捕獲到了異常,但是不想處理,那么可以繼續(xù)向上拋出異常。

int myDivision(int a, int b)
{
	if (b == 0)
	{
		throw -1;
	}
}
void test()
{
	int a = 10;
	int b = 0;
	try
	{
		myDivision(a, b);
	}
	catch (int)
	{
		throw;
	}
}
int main()
{
	try 
	{
		test();
	}
	catch (int)
	{
		cout << "int類型異常捕獲" << endl;
	}
	return 0;
}  

自定義的異常類

注意:類名加()就是匿名對(duì)象

class MyException
{
public:
	void printError()
	{
		cout << "我自己的異常" << endl;
	}
};
int myDivision(int a, int b)
{
	if (b == 0)
	{
		throw  MyException();//類名加()就是匿名對(duì)象,拋出的就是匿名對(duì)象。
	}
}
int main()
{
	int a = 10;
	int b = 0;
	try
	{
		myDivision(a, b);
	}
	catch (MyException e)
	{
		e.printError();//可以直接用這個(gè)對(duì)象來(lái)調(diào)用成員函數(shù)
	}
	return 0;
}

總結(jié):

1,c++中如果出現(xiàn)異常,不像c中return -1,而是直接throw -1,然后后面再用try catch進(jìn)行處理。

2,可能出現(xiàn)異常的地方使用try

3,如果與拋出的異常匹配的處理沒有找到,那么運(yùn)行函數(shù)terminate將被自動(dòng)調(diào)用,其缺省功能調(diào)用abort終止程序。

棧解旋

從try代碼行開始 到 throw將代碼拋出去之前。所有棧上的數(shù)據(jù)會(huì)被自動(dòng)的釋放掉。

釋放的順序和創(chuàng)建的順序是相反的。(棧:先進(jìn)后出)

class Person
{
public:
	Person()
	{
		cout << "Person的默認(rèn)構(gòu)造調(diào)用" << endl;
	}
	~Person()
	{
		cout << "Person的析構(gòu)調(diào)用" << endl;
	}
};
int myDivision(int a, int b)
{
	if (b == 0)
	{
		Person p1;
		Person p2;
		throw  Person();//匿名對(duì)象
	}
}
int main()
{
	int a = 10;
	int b = 0;
	try
	{
		myDivision(a, b);
	}
	catch (Person)
	{
		cout << "拿到Person類異常,正在處理" << endl;
	}
	return 0;
}

輸出結(jié)果:

Person的默認(rèn)構(gòu)造調(diào)用
Person的默認(rèn)構(gòu)造調(diào)用
Person的默認(rèn)構(gòu)造調(diào)用
Person的析構(gòu)調(diào)用
Person的析構(gòu)調(diào)用
拿到Person類異常,正在處理
Person的析構(gòu)調(diào)用

在throw之前創(chuàng)建了兩個(gè)對(duì)象,并拋出一個(gè)匿名對(duì)象。發(fā)現(xiàn)在拋出去之前,兩個(gè)對(duì)象就被釋放了。然后拋出去的對(duì)象在程序結(jié)束時(shí)候釋放。這就是棧解旋

異常接口聲明

只允許拋出規(guī)定類型的異常。

//異常接口的聲明
void func() throw(int , double)//只允許拋出int和double類型的異常。
{
	throw 3.14;
}
int main()
{
	try
	{
		func();
	}
	catch (int)
	{
		cout << "int類型異常捕獲" << endl;
	}
	catch (...)
	{
		cout << "其他類型異常捕獲" << endl;
	}
	return 0;
}

throw()的意思就是不允許拋出異常。

這個(gè)代碼在VS中是不能正確執(zhí)行的,都不會(huì)報(bào)錯(cuò)。但是在QT和linux下是可以正確執(zhí)行的。

異常變量的生命周期

class MyException
{
public:
	MyException()
	{
		cout << "MyException的默認(rèn)構(gòu)造調(diào)用" << endl;
	}
	MyException(const MyException&e)
	{
		cout << "MyException的拷貝構(gòu)造調(diào)用" << endl;
	}
	~MyException()
	{
		cout << "MyException的析構(gòu)調(diào)用" << endl;
	}
};
void doWork()
{
	throw MyException();//拋出匿名對(duì)象
}
int main()
{
	try
	{
		doWork();
	}
	catch (MyException e)
	{
		cout << "自定義異常的捕獲" << endl;	
	}
	return 0;
}

運(yùn)行的結(jié)果:

MyException的默認(rèn)構(gòu)造調(diào)用
MyException的拷貝構(gòu)造調(diào)用
自定義異常的捕獲
MyException的析構(gòu)調(diào)用
MyException的析構(gòu)調(diào)用

throw匿名對(duì)象的時(shí)候創(chuàng)建了對(duì)象,所以用默認(rèn)構(gòu)造。

用MyException e來(lái)接收對(duì)象的時(shí)候,是用的值來(lái)接收的,所以會(huì)調(diào)用拷貝構(gòu)造函數(shù)。

然后就打印,并且將兩個(gè)對(duì)象刪除掉。

這樣效率不高,如果接收對(duì)象的時(shí)候不用值來(lái)接收,而是用引用來(lái)接收,這樣就能少調(diào)用一次的拷貝構(gòu)造和一次析構(gòu)函數(shù)。

catch (MyException &e)
	{
		cout << "自定義異常的捕獲" << endl;	
	}

運(yùn)行結(jié)果:

MyException的默認(rèn)構(gòu)造調(diào)用
自定義異常的捕獲
MyException的析構(gòu)調(diào)用

還有一種方式,就是將匿名函數(shù)的地址穿進(jìn)來(lái),這樣也不需要調(diào)用析構(gòu)函數(shù)。

class MyException
{
public:
	MyException()
	{
		cout << "MyException的默認(rèn)構(gòu)造調(diào)用" << endl;
	}
	MyException(const MyException&e)
	{
		cout << "MyException的拷貝構(gòu)造調(diào)用" << endl;
	}
	~MyException()
	{
		cout << "MyException的析構(gòu)調(diào)用" << endl;
	}
};
void doWork()
{
	throw & MyException();//拋出匿名對(duì)象
}
int main()
{
	try
	{
		doWork();
	}
	catch (MyException *e)
	{
		cout << "自定義異常的捕獲" << endl;	
	}
	return 0;
}

運(yùn)行結(jié)果:(其實(shí)沒有運(yùn)行成功)

MyException的默認(rèn)構(gòu)造調(diào)用
MyException的析構(gòu)調(diào)用
自定義異常的捕獲

如果傳的是指針,那么匿名對(duì)象很快就會(huì)釋放掉(匿名對(duì)象的特點(diǎn)就是執(zhí)行完就釋放掉),最終得到了指針也沒有辦法進(jìn)行操作。

但如果匿名對(duì)象在=的右邊,且左邊還給這個(gè)對(duì)象起名了(如同上面的傳對(duì)象,引用接收),那么匿名對(duì)象的壽命就會(huì)延續(xù)到左邊的變量上。如果傳的是指針,給指針起名和給對(duì)象起名不一樣,所以就會(huì)釋放。

如果不想被釋放掉,還有一種方式,那就是將這個(gè)對(duì)象創(chuàng)建在堆區(qū),等待著程序員自己去釋放。(不會(huì)調(diào)用析構(gòu))

void doWork()
{
	throw new MyException();//拋出匿名對(duì)象
}

異常的多態(tài)

//異常的基類
class BaseException
{
public:
	virtual void printError() = 0;//純虛函數(shù)
};
//空指針異常
class NULLPointerException:public BaseException
{
public:
	virtual void printError()
	{
		cout << "空指針異常" << endl;
	}
};
//越界異常
class outOfRangeException :public BaseException
{
public:
	virtual void printError()
	{
		cout << "越界異常" << endl;
	}
};
void doWork()
{
	//throw NULLPointerException();
	throw outOfRangeException();
}
int main()
{
	try
	{
		doWork();
	}
	catch (BaseException &e)//用父類的引用接收子類的對(duì)象
	{
		e.printError();
	}
	return 0;
}

提供一個(gè)基類的異常類,其中有個(gè)純虛函數(shù)(有可能是虛函數(shù)),然后子類重寫。

調(diào)用的時(shí)候,用父類的引用來(lái)接收子類的對(duì)象就可以,這樣就實(shí)現(xiàn)了異常的多態(tài)。拋出的是什么類的對(duì)象,那么就會(huì)調(diào)用什么類的函數(shù)。

c++的標(biāo)準(zhǔn)異常庫(kù)

img

標(biāo)準(zhǔn)庫(kù)中提供了很多的異常類,它們是通過類繼承組織起來(lái)的。

如果使用系統(tǒng)提供的標(biāo)準(zhǔn)異常的時(shí)候,需要調(diào)用規(guī)定的頭文件

#include <stdexcept>std:標(biāo)準(zhǔn) except:異常

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include<string>
#include<stdexcept>
class Person
{
public:
	Person(int age)
	{
		if (age < 0 || age>150)
		{
			throw out_of_range("年齡必須在0-150之間");
		}
	}
	int m_age;
};
int main()
{
	try
	{
		Person p(151);
	}
	catch (out_of_range&e)
	{
		cout << e.what() << endl;//what函數(shù)是獲得字符串中的內(nèi)容
	}
	return 0;
	//如果使用多態(tài):(異常子類的名字太難記,不好寫)
	//catch (exception &e)
}

自己平時(shí)不會(huì)主動(dòng)調(diào)用系統(tǒng)的標(biāo)準(zhǔn)異常。在寫的系統(tǒng)提供的異常后面加()的字符串然后在接收的時(shí)候用父類的引用接收,然后用這個(gè)引用e的what函數(shù)就可以找到這個(gè)字符串。

編寫自己的異常類

標(biāo)準(zhǔn)異常類是優(yōu)先的,可以自己編寫異常類。

和上面自己寫的MyException不太一樣。給系統(tǒng)提供的派生類exception提供兒子(需要重寫父類的函數(shù)等)

ps:在非靜態(tài)成員函數(shù)后面加const,表示成員函數(shù)隱含傳入的this指針為const指針,決定了在該成員函數(shù)中,任意修改它所在的類的成員操作是不允許的。

經(jīng)過考察上面的有關(guān)out_of_range的代碼可得:拋出的是out_of_range類的一個(gè)對(duì)象,接收的時(shí)候也是用引用e來(lái)接收的這個(gè)對(duì)象。然后這個(gè)引用可以調(diào)用what()的函數(shù)來(lái)返回一個(gè)字符串,這個(gè)字符串正好是創(chuàng)建out_of_range對(duì)象的時(shí)候待用有參函數(shù)要傳入的 字符串。

所以,自己寫的out_of_range類一定要有個(gè)有參構(gòu)造,參數(shù)就是字符串,然后還有個(gè)what的重寫函數(shù),需要返回這個(gè)字符串,這個(gè)字符串作為屬性。

ps:注意:const char*可以隱式轉(zhuǎn)換為string,但是反過來(lái)就不成立。

所以如果要使得string轉(zhuǎn)換成const char*,需要調(diào)用string中的成員函數(shù)函數(shù).c_str()

const char* what() const
{
    string s;
    return s.c_str();
    //返回的就是const char*了。
}

完整代碼:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include<string>
#include<stdexcept>
class MyOutOfRangeException:public exception//先繼承一下這個(gè)父親
{
	//到底要重寫什么呢?點(diǎn)開exception以后,發(fā)現(xiàn)有兩個(gè)virtual的虛函數(shù),一個(gè)析構(gòu),還有一個(gè)what,析構(gòu)不需要重寫
	//所以需要重寫what函數(shù)。
public:
	MyOutOfRangeException(const char* str)
	{
		//const char*可以隱式類型轉(zhuǎn)換為string 反之不可以
		this->m_myerrorString = str;
	}
	//可以再重載一下這個(gè)函數(shù),使得接收的參數(shù)改為string類型
	MyOutOfRangeException(string str)
	{
		this->m_myerrorString = str;
	}
	virtual char const* what() const
	{
		return m_myerrorString.c_str();//加了.c_str就可以返回const char*了
	}
	string m_myerrorString;//字符串屬性
};
class Person
{
public:
	Person(int age)
	{
		if (age < 0 || age>150)
		{
			throw MyOutOfRangeException("年齡必須在0-150之間");//const char*
			throw MyOutOfRangeException(string("年齡必須在0-150之間"));//string,返回的是string類的匿名對(duì)象
		}
		else
		{
			this->m_age = age;
		}
	}
	int m_age;
};
int main()
{
	try
	{
		Person p(1000); 
	}
	catch (MyOutOfRangeException e)//用exception也可以,證明創(chuàng)建的這個(gè)類確實(shí)是exception的子類。
	{
		cout << e.what() << endl;
	}
	return 0;
}

但是最后發(fā)現(xiàn)好像沒有成功的將MyOutOfRangeException手寫異常類變成exception的子類,不知道為啥。

總結(jié)

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!                

相關(guān)文章

  • C++將字符串格式化的幾種方式總結(jié)

    C++將字符串格式化的幾種方式總結(jié)

    這篇文章主要介紹了C++將字符串格式化的幾種方式總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • C語(yǔ)言中宏定義的妙用方法

    C語(yǔ)言中宏定義的妙用方法

    今天小編就為大家分享一篇關(guān)于C語(yǔ)言中宏定義的妙用方法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • 詳解C++編程中標(biāo)記語(yǔ)句與復(fù)合語(yǔ)句的寫法

    詳解C++編程中標(biāo)記語(yǔ)句與復(fù)合語(yǔ)句的寫法

    這篇文章主要介紹了C++編程中標(biāo)記語(yǔ)句與復(fù)合語(yǔ)句的寫法,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2016-01-01
  • opencv攝像頭捕獲識(shí)別顏色

    opencv攝像頭捕獲識(shí)別顏色

    這篇文章主要介紹了opencv攝像頭捕獲識(shí)別顏色,用opencv通過攝像頭捕獲識(shí)別顏色,紅色藍(lán)色等,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • Visual Studio Code上添加小程序自動(dòng)補(bǔ)全插件的操作方法

    Visual Studio Code上添加小程序自動(dòng)補(bǔ)全插件的操作方法

    這篇文章主要介紹了Visual Studio Code上添加小程序自動(dòng)補(bǔ)全插件的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • linux系統(tǒng)中c++寫日志文件功能分享

    linux系統(tǒng)中c++寫日志文件功能分享

    這篇文章主要介紹了linux系統(tǒng)中c++寫日志文件功能,簡(jiǎn)化了glog,只保留了寫日志文件的功能,只是改寫了linux版本,需要的朋友可以參考下
    2014-03-03
  • 一文帶你了解Qt多線程的實(shí)現(xiàn)方式

    一文帶你了解Qt多線程的實(shí)現(xiàn)方式

    這篇文章主要為大家詳細(xì)介紹了Qt多線程的實(shí)現(xiàn)方式的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-01-01
  • Qt使用Matlab函數(shù)的詳細(xì)步驟

    Qt使用Matlab函數(shù)的詳細(xì)步驟

    由于項(xiàng)目需要,需要調(diào)用現(xiàn)有的matlab程序,下面這篇文章主要給大家介紹了關(guān)于Qt使用Matlab函數(shù)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • C++中的菱形繼承深入分析

    C++中的菱形繼承深入分析

    這篇文章主要介紹了C++中的菱形繼承深入分析的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • C++之&與*符號(hào)用法案例詳解

    C++之&與*符號(hào)用法案例詳解

    這篇文章主要介紹了C++之&與*符號(hào)用法案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09

最新評(píng)論

河北区| 寿宁县| 大田县| 东辽县| 通城县| 浦城县| 通榆县| 靖安县| 吉木乃县| 枞阳县| 云梦县| 阿合奇县| 葫芦岛市| 白河县| 延安市| 额敏县| 东方市| 龙门县| 万荣县| 扶绥县| 通榆县| 莲花县| 旬邑县| 遂平县| 罗城| 北碚区| 诸暨市| 故城县| 凤台县| 河东区| 西青区| 石景山区| 静乐县| 历史| 洪洞县| 托克托县| 秦安县| 体育| 定安县| 耿马| 合水县|