现在的位置: 首页 > 综合 > 正文

自定义自加自减下标解引用等问题–围绕CheckedPtr类 续14.26题

2012年09月04日 ⁄ 综合 ⁄ 共 7132字 ⁄ 字号 评论关闭

pe14_26_2.cpp//dui 26题的优化

适当的const保护,还有操作符函数的定义顺序最好遵从声明顺序,看起来清晰一点

#include"head.h"
//版本二,优化加减法判断问题,我要把加负数的情况直接转化为调用减法,反之相反
//调用相反操作符时传递参数要注意,传入(0 - change)有个转化
class CheckedPtr{
public:
	CheckedPtr(int* b, int* e): beg(b), end(e), curr(b) {}
public:
	CheckedPtr& operator++();
	CheckedPtr& operator--();
	//添加一个没用的形参,来实现重载,此外,可以利用这个显式调用后缀操作,注意后缀返回的是原副本
	CheckedPtr operator++(int);
	CheckedPtr operator--(int);
	
	int& operator*();
	int& operator[](unsigned);
	
	bool operator<(const CheckedPtr&);//为该类增加这些操作:指的是成员函数把?
	bool operator==(const CheckedPtr&);
	//加减数字来调整指针指向,返回一个副本,指向新位置
	CheckedPtr operator+(int);
	CheckedPtr operator-(int);
	
public:
	int getCurr(){return *curr;}
private:
	int* beg;
	int* end;
	int* curr;
};

CheckedPtr&  CheckedPtr::operator++(){
	if(curr == end)
		throw std::out_of_range//<stdexcept>,之前那些都不能用,今次能用了啊,(可能catch之类的还是不行把,那块跳过了)
			("increment past the end of CheckedPtr");
	++curr;
	return *this;
}
CheckedPtr&  CheckedPtr::operator--(){
	if(curr == beg)
		throw std::out_of_range
			("decrement past the beginning of CheckedPtr");
	--curr;
	return *this;
}
CheckedPtr CheckedPtr::operator++(int){
	CheckedPtr ret(*this);
	++*this;//调用了前缀操作
	return ret;	
}
CheckedPtr CheckedPtr::operator--(int){
	CheckedPtr ret(*this);
	--*this;//调用了前缀操作
	return ret;	
}


int& CheckedPtr::operator*(){
	if(curr > end || curr < beg)
		throw std::out_of_range
			("out of range~!");
	return *curr;
}
int& CheckedPtr::operator[](unsigned index){
	if(index >= (end - beg) || index < 0)
		throw std::out_of_range
			("out of range~!");
	int * temp = curr;//需要对原位置进行一个保护
	curr = beg;//重置curr,保证每次都是从0计算,得到正确下标
	for(unsigned i = 0; i < index; i++)
		curr++;
	int* ret = curr;
	std::cout << "test\t*curr: " << *curr << std::endl;
	curr = temp;//还原curr
	std::cout << "test\t*curr: " << *curr << std::endl;
	return *ret;//既要保护原curr位置,在返回前还原,又要返回引用供修改,我认为办不到。。。。。。。。。。。。。。
	//I did it~!!!!!!!!!!!!!!!1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
}



bool CheckedPtr::operator<(const CheckedPtr& rhs){
	if((curr - beg) < (rhs.curr - rhs.beg))
		return 1;
	return 0;
}
bool CheckedPtr::operator==(const CheckedPtr& rhs){
	if((curr - beg) == (rhs.curr - rhs.beg))
		return 1;
	return 0;	
}
//两指针相加有什么意义
//(lhs.curr - lhs.beg) + (rhs.curr - rhs.beg) - lhs.beg;
//太麻烦了
//int operator+(const CheckedPtr& lhs, const CheckedPtr& rhs){
	
/*指针减,返回差值,可以是正负,前提也是同一数组
int operator-(const CheckedPtr& lhs, const CheckedPtr& rhs){
	return (lhs.curr - rhs.curr);//private,还要定义成成员	
}
* 意义不大,还是用指针加减数字有用
*/

CheckedPtr CheckedPtr::operator+(const int change){//不限制正负号会比较麻烦,只为满足 ptr + (-10);这种操作
	if(change < 0){
		CheckedPtr ret = this->operator-(0 - change);
		return ret;
	}
	else{
		if((curr + change) < beg || (curr + change) >= end)//还要判断出界问题
			throw std::out_of_range
				("out of range");
		CheckedPtr ret(beg, end);
		ret.curr = curr;//必要:不然加法不具备累积性,ptr + 1; ptr + 2;总共算+2
		if(change >= 0)
		for(int i = 0; i < change; i++)
			ret++;
		return ret;
	}
}

CheckedPtr CheckedPtr::operator-(const int change){//不限制正负号会比较麻烦,只为满足 ptr - (-10);这种操作
	if(change < 0){
		CheckedPtr ret = this->operator+(0 - change);
		return ret;
	}
	else{	
		if((curr - change) < beg || (curr - change) >= end)//还要判断出界问题
			throw std::out_of_range
				("out of range");
		CheckedPtr ret(beg, end);
		ret.curr = curr;//必要:不然加法不具备累积性,ptr + 1; ptr + 2;总共算+2
		for(int i = 0; i < change; i++)
			ret--;
		return ret;
	}
}	
	
int main(){
	
	const unsigned size = 10;
	int a[size] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
	CheckedPtr ptr1(a, a + size);
	CheckedPtr ptr2(a, a + size);
	//测试加法
	std::cout << *ptr2 << std::endl;
	ptr2 = ptr2 + 3;
	std::cout <<  "after ptr2 + 3 : " << *ptr2 << std::endl;
	ptr2 = ptr2 + 4;
	std::cout <<  "after ptr2 + 4 : " << *ptr2 << std::endl;
	ptr2 = ptr2 + (-1);//加负数,另一种思路是用判断条件,如果有加负数,直接调用减法操作符,有待添加(已修改)
	std::cout <<  "after ptr2 + (-1) : " << *ptr2 << std::endl;
	ptr2 = ptr2 - 1;
	std::cout << "after ptr2 - 1 : " << *ptr2 << std::endl;
	ptr2 = ptr2 - (-1);//减负数,另一种思路是用判断条件,如果有减负数,直接调用加法操作符,有待添加(已修改)
	std::cout << "after ptr2 - (-1) : " <<  *ptr2 << std::endl;
	//ptr2 - (-2);//越上界
	//ptr2 = ptr1 + 11;//测试越界
	//ptr
}

14.24

下标和解引用是否需要对数组起点之前的元素进行检查,下标不用,我传的是unsigned,从0开始,解引用就更不用了,因为整个类对象已经有了curr的越界检查,所以对象不能有超界状态。

14.27

允许构造函数传入数组实参,缺点是边界判断,相比(beg, end),传入数组没有end,不过可以用size()自己去判断吧(状态不佳,扔着了)

14.28没定义自增和自减操作符的const版本,为什么

因为要改变成员curr,不同于一般意义的指针自加自减

14.29

为什么不实现箭头操作符

怕理解不便吧,需要的箭头操作是取数组的某元素吧,箭头操作符也可以是取对象的成员,引起误解

14.30再定义一个CheckedPtr版本,保存Screen数组,为该类实现重载的自增、自减、解引用、箭头等操作。

#include"head.h"
//保存Screen数组用,并定义各种操作
class Screen{
public:	
	typedef std::string::size_type index;//利用typedef
	char get() const{
		//return contents[cursor];
		return 'T';//test
	}//重载
	void setTest(index i = 1){cursor = i;}
	index getTest(){return cursor;}
	inline char get(index ht, index wd) const;//显式定义inline
	index get_cursor() const;//后者便于阅读,在类的定义里的声明比较清晰
public:
	Screen(index ht, index wd): height(ht), width(wd) {}
	Screen(): height(0), width(0) {}
private:
	std::string contents;
	index cursor;//光标
	index height, width;//同时声明多个
};
	

class CheckedPtr{
public:
	CheckedPtr(Screen* b, Screen* e): beg(b), end(e), curr(b) {}
public:
	CheckedPtr& operator++();
	CheckedPtr& operator--();
	//添加一个没用的形参,来实现重载,此外,可以利用这个显式调用后缀操作,注意后缀返回的是原副本
	CheckedPtr operator++(int);
	CheckedPtr operator--(int);
	
	Screen& operator*();
	Screen& operator[](unsigned);
	
	bool operator<(const CheckedPtr&);//为该类增加这些操作:指的是成员函数把?
	bool operator==(const CheckedPtr&);
	//加减数字来调整指针指向,返回一个副本,指向新位置
	CheckedPtr operator+(int);
	CheckedPtr operator-(int);
	
public:
	Screen getCurr(){return *curr;}
private:
	Screen* beg;
	Screen* end;
	Screen* curr;
};

CheckedPtr&  CheckedPtr::operator++(){
	if(curr == end)
		throw std::out_of_range//<stdexcept>,之前那些都不能用,今次能用了啊,(可能catch之类的还是不行把,那块跳过了)
			("increment past the end of CheckedPtr");
	++curr;
	return *this;
}
CheckedPtr&  CheckedPtr::operator--(){
	if(curr == beg)
		throw std::out_of_range
			("decrement past the beginning of CheckedPtr");
	--curr;
	return *this;
}
CheckedPtr CheckedPtr::operator++(int){
	CheckedPtr ret(*this);
	++*this;//调用了前缀操作
	return ret;	
}
CheckedPtr CheckedPtr::operator--(int){
	CheckedPtr ret(*this);
	--*this;//调用了前缀操作
	return ret;	
}


Screen& CheckedPtr::operator*(){
	if(curr > end || curr < beg)
		throw std::out_of_range
			("out of range~!");
	return *curr;
}
Screen& CheckedPtr::operator[](unsigned index){
	if(index >= (end - beg) || index < 0)
		throw std::out_of_range
			("out of range~!");
	Screen * temp = curr;//需要对原位置进行一个保护
	curr = beg;//重置curr,保证每次都是从0计算,得到正确下标
	for(unsigned i = 0; i < index; i++)
		curr++;
	Screen* ret = curr;
	std::cout << "test\t*curr: " << curr->getTest() << std::endl;
	curr = temp;//还原curr
	std::cout << "test\t*curr: " << curr->getTest() << std::endl;
	return *ret;
}



bool CheckedPtr::operator<(const CheckedPtr& rhs){
	if((curr - beg) < (rhs.curr - rhs.beg))
		return 1;
	return 0;
}
bool CheckedPtr::operator==(const CheckedPtr& rhs){
	if((curr - beg) == (rhs.curr - rhs.beg))
		return 1;
	return 0;	
}
//两指针相加有什么意义
//(lhs.curr - lhs.beg) + (rhs.curr - rhs.beg) - lhs.beg;
//太麻烦了
//int operator+(const CheckedPtr& lhs, const CheckedPtr& rhs){
	
/*指针减,返回差值,可以是正负,前提也是同一数组
int operator-(const CheckedPtr& lhs, const CheckedPtr& rhs){
	return (lhs.curr - rhs.curr);//private,还要定义成成员	
}
* 意义不大,还是用指针加减数字有用
*/

CheckedPtr CheckedPtr::operator+(const int change){//不限制正负号会比较麻烦,只为满足 ptr + (-10);这种操作
	if(change < 0){
		CheckedPtr ret = this->operator-(0 - change);
		return ret;
	}
	else{
		if((curr + change) < beg || (curr + change) >= end)//还要判断出界问题
			throw std::out_of_range
				("out of range");
		CheckedPtr ret(beg, end);
		ret.curr = curr;//必要:不然加法不具备累积性,ptr + 1; ptr + 2;总共算+2
		if(change >= 0)
		for(int i = 0; i < change; i++)
			ret++;
		return ret;
	}
}

CheckedPtr CheckedPtr::operator-(const int change){//不限制正负号会比较麻烦,只为满足 ptr - (-10);这种操作
	if(change < 0){
		CheckedPtr ret = this->operator+(0 - change);
		return ret;
	}
	else{	
		if((curr - change) < beg || (curr - change) >= end)//还要判断出界问题
			throw std::out_of_range
				("out of range");
		CheckedPtr ret(beg, end);
		ret.curr = curr;//必要:不然加法不具备累积性,ptr + 1; ptr + 2;总共算+2
		for(int i = 0; i < change; i++)
			ret--;
		return ret;
	}
}	
	
int main(){
	
	const unsigned size = 10;
	Screen s[size];
	
	s[1].setTest(8);

	std::cout << s[1].getTest() << std::endl;
	CheckedPtr ptr(s, s + size - 1);
	std::cout << (*++ptr).getTest() << std::endl;
	std::cout << (*++ptr).getTest() << std::endl;
	std::cout << ptr[5].getTest() << std::endl;
	
	
}

抱歉!评论已关闭.