栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ 异常处理和智能指针

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ 异常处理和智能指针

目录

1. 异常处理

2. C++11 智能指针

3. 典型范例——设计和实现向量类模板


1. 异常处理

基本思想:底层检测到异常情况时抛出(throw)异常、高层可以处理异常时检查并捕捉(str...catch)异常两部分

异常的抛出和捕获:

#include 
#include 
using namespace std;

double Area(double a, double b, double c)
{
    if (a + b <= c || b + c <= a || c + a <= b)
    {
        throw "Doesn't meet the condisions of the triangle";    //异常抛出
    }
    double p = (a + b + c) / 2;
    return std::sqrt(p * (p - a) * (p - b) * (p - c));
}

int main()
{
    try    //可能抛出异常的序列
    {
        cout << Area(3, 4, 5) << endl;
        cout << Area(3, 4, 8) << endl;
        cout << Area(3, 3, 3) << endl;
    }
        catch (const char* errMsg)
    {
        cout << errMsg << endl;
    }
}

catch子句是按顺序匹配的,前面的catch子句完成匹配后,后续的catch子句不会再进行匹配

#include 
#include 
using namespace std;

class A
{
private:
	char mess[18];
public:
	A()
	{
		strcpy(mess, "基类 A ");
	}
	const char* GetMess()const
	{
		return mess;
	}
};

class B : public A
{
private:
	char mess[18];
public:
	B()
	{
		strcpy(mess, "派生类 B ");
	}
	const char* GetMess()const
	{
		return mess;
	}
};

int main()
{
	try
	{
		throw B();
	}
	catch (const B& b)
	{
		cout << b.GetMess() << "类型的异常" << endl;
	}
	catch (const A& a)
	{
		cout << a.GetMess() << "类型的异常" << endl;
	}
	return 0;
}
  • 异常的处理:若异常未被捕获,系统调用std::terminate()函数终止程序执行
  • 标准库异常分类:C++标准库提供了已定义异常类型,所有这些异常类型都派生自基类:exception
try
{
	//可能抛出的异常
}
catch (exception& e)
{
	//处理异常的语句
}

2. C++11 智能指针

智能指针类模板设计和实现:

#include 
#include 
using namespace std;

class Song
{
public:
	Song(string strName) :m_strName(strName) {};
	~Song()
	{
		cout << "Song Destructor called" << endl;
	}
	void Play()
	{
		cout << "Play song " << m_strName << endl;
	}
private:
	string m_strName;
};

class Dog
{
public:
	~Dog()
	{
		cout << "Dog Destructor called" << endl;
	}
	void Bark()
	{
		cout << "Bark! Bark!" << endl;
		throw 1;
	}
};

template
class smart_ptr		//智能指针模板原型
{
private:
	T* m_pRawPointer;
public:
	smart_ptr(T* pData) :m_pRawPointer(pData) {}
	~smart_ptr()
	{
		delete m_pRawPointer;
	}
	T& operator*()const	//重载解引用符*
	{
		return *(m_pRawPointer);
	}
	T* operator->()const	//重载运算符->
	{
		return m_pRawPointer;
	}
	smart_ptr(smart_ptr&& anotherSP)	//移动构造
	{
		m_pRawPointer = anotherSP.m_pRawPointer;
		anotherSP.m_pRawPointer = nullptr;
	}
	smart_ptr& operator=(smart_ptr&& anotherSP)	//移动赋值
	{
		swap(m_pRawPointer, anotherSP.m_pRawPointer);
	}
	smart_ptr(const smart_ptr& anotherSP) = delete;	//禁止复制构造
	smart_ptr& operator=(const smart_ptr& anotherSP) = delete;	//禁止复制赋值
};

int main()
{
	try
	{
		smart_ptr smartPtrSong(new Song("Nothing on You"));
		smartPtrSong->Play();
		smart_ptr smartPtrDog(new Dog);
		smartPtrDog->Bark();
	}
	catch (...){}
	return 0;
}

unique_ptr: 适用于管理只有一个所有者的动态分配资源场合

void someFuntion()
{
	unique_ptrpMc(new MyClass);
	pMc->DoSomeWork();
}

unique_ptr类模板的简化定义:

template
class unique_ptr
{
public:
	unique_ptr(T* p = nullptr);		//构造函数,记住资源对象
	~unique_ptr();					//析构函数,删除资源对象
	T& operator*()const;			//重载解引用运算符*,非空状态才能使用
	T* operator->()const;			//重载选择运算符->,非空状态才能使用
	unique_ptr(unique_ptr&& anotherUP);				//移动构造
	unique_ptr& operator=(unique_ptr&& anotherUP);	//移动赋值
	unique_ptr(const unique_ptr& anotherUP) = delete;				//禁止赋值构造
	unique_ptr& operator=(const unique_ptr& anotherUP) = delete;	//禁止复制赋值
	operator bool()const;				//非空时为true,空时为false
	void reset(T* p = nullptr);			//删除源资源对象,托管新对象
	T* get();							//返回资源对象原始指针,托管关系不变
	T* relase();						//放弃托管关系,返回资源对象原始指针,成为空状态
};

unique_ptr的一些样例片段:

unique_ptr up;	//管理T类型对象的智能指针对象,处于空状态
up.reset(new T);	//托管新对象
if (up)
{
	*up;			//所指对象引用,非空是才可以使用
	up->member;		//所指对象成员,非空是才可以使用
}
p = up.get();		//获得传统“裸指针”,保留管理权
p = up.relase();	//放弃管理权


//智能指针的创建
unique_ptr u_i;
u_i.reset(new int(3));
unique_ptr u_i2(new int(4));

//所有权的变化
//u_i2 = u_i;			//错误,不可以重复赋值
u_i2 = std::move(u_i);	//正确,可以移动赋值
int* p_i = u_i2.relase();	//放弃管理权
unique_ptr u_s(new string("abc"));	//创建字符串智能指针
unique_ptr u_s2 = std::move(u_s);	//移动构造
u_s2 = nullptr;		//显式销毁所指对象

shared_ptr: 适用于多个对象共同拥有动态分配资源的场合

#include 
#include 
#include 
#include 
using namespace std;

template 
void fun()
{
	shared_ptr sp;
	sp.reset(new t());
	if (sp)
	{
		*sp;
		//sp->member;
	}
	t* p = sp.get();
	cout << *p << endl;
}

int main()
{
	fun();
	fun();
	shared_ptr s_i;
	assert(s_i.use_count() == 0);
	s_i.reset(new int(0));
	assert(s_i.use_count() == 1);
	auto s_i2 = make_shared(2);
	{
		shared_ptr s_i3(new int(3));
		cout << *s_i3 << endl;
		s_i3 = s_i;
		cout << *s_i3 << endl;
		*s_i = 1;
		cout << *s_i3 << endl;
		assert(s_i.use_count() == 2);
		assert(s_i3.use_count() == 2);
	}
	assert(s_i.use_count() == 1);
	shared_ptr s_s(new string("abc"));
	shared_ptr s_s2 = s_s;
	cout << *s_s2 << endl;
	auto s_s3 = make_shared("hello");
	s_s2 = nullptr;
	cout << *s_s << endl;
	return 0;
}

weak_ptr: 弱指针

weak_ptr类模板的简化定义

template
class weak_ptr
{
public:	
	weak_ptr();	//构造函数,建立空指针
	explicit weak_ptr(const share_ptr& anotherSP); //建立关联共享指针的弱指针
	weak_ptr& operator=(const shared_ptr& anotherSP); //更新关联的共享智能指针
	weak_ptr(const weak_ptr& anotherWP); //拷贝构造
	weak_ptr& operator=(const weak_ptr& anotherWP);	//复制赋值
	long use_const()const;	//返回关联的共享智能指针的资源对象引用计数,主要用于调试
	bool expored()const;	//关联的共享智能指针是否过期
	shared_ptr lock(); //返回关联的共享智能指针,过期时返回空状态指针
	void reset();	//重置为空指针
};

说明弱指针weak_ptr常用接口使用方法的简单样例:

#include 
#include 
using namespace std;

struct A
{
	A(int iv) :m_iValue(iv) {}
	~A()
	{
		cout << "A 类对象析构" << endl;
	}
	int m_iValue;
};

void TestWeakPtr(weak_ptr wp)
{
	shared_ptr sp;
	cout << wp.expired() << endl;
	cout << wp.use_count() << endl;
	if (sp = wp.lock())
	{
		cout << "success, value" << sp->m_iValue << endl;
	}
	else
	{
		cout << "empty" << endl;
	}
}

int main()
{
	shared_ptr sp1(new A(1)), sp2;
	weak_ptr wp1, wp2(sp1), wp3(wp2);
	TestWeakPtr(wp1);
	TestWeakPtr(wp2);
	TestWeakPtr(wp3);
	{
		shared_ptr sp3(new A(2));
		wp3 = sp3;
		TestWeakPtr(wp3);
		wp2 = wp3;
		TestWeakPtr(wp2);
	}
	TestWeakPtr(wp2);
	return 0;
}

3. 典型范例——设计和实现向量类模板
#include 
#include 
#include 
#include 
#include 
using namespace std;

//异常对象类
class CException :public exception
{
private:
	string m_errMsg;
public:
	CException(string errMsg, int i) :m_errMsg(errMsg)
	{
		stringstream stream;
		stream << i;
		string str;
		stream >> str;
		m_errMsg += str;
	}
	const char* what()const noexcept
	{
		return m_errMsg.c_str();
	}
};

template 
class CMyVector
{
private:
	T* m_pBuffer;
	int m_size, m_bufferSize;
public:
	CMyVector() :m_pBuffer(nullptr), m_size(0), m_bufferSize(0) {}
	CMyVector(int n) :m_pBuffer(nullptr), m_size(n), m_bufferSize(n)
	{
		if (m_bufferSize > 0)
		{
			m_pBuffer = new T[m_bufferSize];
		}
	}
	~CMyVector()
	{
		delete[] m_pBuffer;
	}
	CMyVector(const CMyVector& rhs);	//复制构造
	CMyVector(CMyVector&& rhs);		//C++11 移动构造
	CMyVector& operator=(const CMyVector& rhs);	//复制赋值
	CMyVector& operator=(CMyVector && rhs);	//C++11 移动赋值
	void push_back(const T& rhs);	//尾部添加元素
	T& at(int i)
	{
		if (i < 0 || i >= m_size)
		{
			string errMsg("invail index:");
			throw CException(errMsg, i);
		}
		return m_pBuffer[i];
	}
	T& operator[](int i)
	{
		return m_pBuffer[i];
	}
	int size()const
	{
		return m_size;
	}
};

template
void CMyVector::push_back(const T& rhs)
{
	if (m_bufferSize <= m_size)
	{
		CMyVector tmpVect;
		tmpVect.m_bufferSize = m_bufferSize * 2 + 1;
		tmpVect.m_pBuffer = new T[tmpVect.m_bufferSize];
		tmpVect.m_size = m_size;
		for (int i = 0; i < m_size; i++)
		{
			tmpVect.m_pBuffer[i] = m_pBuffer[i];
		}
		swap(*this, tmpVect);
	}
	m_pBuffer[m_size++] = rhs;
}

template
CMyVector::CMyVector(const CMyVector& rhs) :
	m_pBeffer(nullptr), m_size(rhs.m_size), m_bufferSize(rhs.m_bufferSize)
{
	if (m_bufferSize == 0)
	{
		return;
	}
	m_pBuffer = new T[m_bufferSize];
	for (int i = 0; i < m_size; i++)
	{
		m_pBuffer[i] = rhs.m_pBuffer[i];
	}
}

template
CMyVector::CMyVector(CMyVector&& rhs) :
	m_pBuffer(rhs.m_pBuffer), m_size(rhs.size), m_bufferSize(rhs.m_bufferSize)
{
	rhs.m_pBuffer = nullptr;
	rhs.m_size = 0;
	rhs.m_bufferSize = 0;
}

template
CMyVector& CMyVector::operator=(const CMyVector& rhs)
{
	CMyVector tmpVect(rhs);
	//下面三条语可替换为swap(*this, tmpVect)
	swap(m_pBuffer, tmpVect.m_pBuffer);
	swap(m_bufferSize, tmpVect.m_bufferSize);
	swap(m_size, tmpVect.m_size);
	return *this;
}

template
CMyVector& CMyVector::operator=(CMyVector&& rhs)
{
	swap(m_pBuffer, rhs.m_pBuffer);
	swap(m_bufferSize, rhs.m_bufferSize);
	swap(m_size, rhs.size);
	return *this;
}

template
void Parse(int size)
{
	CMyVector V(size);
	string cmd;
	T x;
	int index;
	while (cin >> index)
	{
		try
		{
			if (cmd == "quit")
			{
				break;
			}
			else if (cmd == "push")
			{
				cin >> x;
				V.push_back(x);
			}
			else if (cmd == "fetch")
			{
				cin >> index;
				x = V.at(index);
				cout << ' ' << x;
			}
			else if (cmd == "put")
			{
				cin >> index >> x;
				V.at(index) = x;
			}
		}
		catch (exception& ex)
		{
			cout << ' ' << ex.what();
		}
	}
	cout << endl;
}

int main()
{
	string typeStr;
	while (cin >> typeStr)
	{
		int size;
		cin >> size;
		if (typeStr == "int")
		{
			Parse(size);
		}
		else
		{
			Parse(size);
		}
	}
	return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/971815.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号