《C++primer》操作符重载之CheckoutRecord相关


有个稍微特殊的容器成员,定义从输入到输出,到下标等的一系列操作符


 PE14.7

//为下面的类顶一个一个输出操作符,

#include"head.h"

class CheckoutRecord{
public:
	CheckoutRecord(std::vector< std::pair<std::string, std::string>* > wait_list): book_id(0.0), title("hell"), date_borrowed(1988), date_due(1999),
						borrower(std::make_pair("hu", "qw")), wait_list(wait_list){}
	CheckoutRecord(): book_id(0.0), title("hell"), date_borrowed(1988), date_due(1999),
						borrower(std::make_pair("hu", "qw")){}
						
	friend std::ostream&
	operator<<(std::ostream&, const CheckoutRecord&);
	typedef unsigned Date;
private:
	double book_id;
	std::string title;
	//借书还书日期
	Date date_borrowed;//Date是标准库的?先自定义一个
	Date date_due;//
	std::pair<std::string, std::string> borrower;//用pair存放单个借阅者的名字
	std::vector< std::pair<std::string, std::string>* > wait_list;//vector存储(指向每个排队者)的指针
	
};

std::ostream&
operator<<(std::ostream& out, const CheckoutRecord& check){
	out << check.book_id << "\t" << check.title
		<< "\t" << check.date_borrowed << "\t" << check.date_due
		 << "\t" << check.borrower.first << "\t" << check.borrower.second;
		 
		 for(std::vector< std::pair<std::string, std::string> *>::const_iterator iter = check.wait_list.begin();
		  iter != check.wait_list.end(); iter++){//循环输出排队列表
			  out << std::endl << "第" << (iter - check.wait_list.begin()) + 1 << "排队者: " <<(*iter)->first << "\t" << (*iter)->second;
			  
		  }
	return out;
}
int main(){
	//声明定义一个排队列表
	std::vector< std::pair<std::string, std::string>* > wait_list;
	
	std::string first_name = "holy";
	std::string second_name = "god";
	std::pair<std::string, std::string> name2 = std::make_pair("zhang", "lixin");
	wait_list.push_back(&name2);//其他三个有warning,因为是make_pair临时变量
	wait_list.push_back(&std::make_pair(first_name, second_name));
	wait_list.push_back(&std::make_pair(first_name, first_name));
	wait_list.push_back(&std::make_pair(second_name, first_name));//为什么这个输出不按格式走呢,与位置无关,放那都一样
	
	CheckoutRecord check1(wait_list);
	std::cout << check1 << std::endl;
}


pe14_11

//输入操作符,要求对错误处理,最后一个成员肯定不是能in的
std::istream&
operator>>(std::istream& in, CheckoutRecord& check){
	in >> check.book_id >> check.title
		>> check.date_borrowed >> check.date_due
		 >> check.borrower.first>>check.borrower.second;
	if(!in)
		check = CheckoutRecord();
		 
	return in;
}

pe14_17




//定义下标操作符,下标操作符要考虑返回的是个左值,被赋值的情况,check1[1]->first = "asd";所以需要一个非const

std::pair<std::string, std::string>* CheckoutRecord::operator[](const size_t index){ return wait_list[index]; } const std::pair<std::string, std::string>* CheckoutRecord::operator[](const size_t index) const{//返回的都是指针,无所谓const了,反正都能改队列内容pair return wait_list[index]; } int main(){ std::cout << check1[1]->first << "\t" << check1[1]->second << std::endl; }

pe14_18//优点,操作方便,缺点,类有很多成员,而下标只是排队列表的pair的指针,怕是不通俗,不好理解

另一人为缺点是不进行下标越界检查,实际上用wait_list.size()对比一下就型了把

pe14_19//提出另一种方法定义这个操作:用函数吧,可以定义一个和下标操作符实现完全一样的getQueueMember(),只有名字不一样,但这解决了不便于理解的问题。

要不getQueueMemberFirst、getQueueMemberSecond(),

要么就在实现里自己取出来字符串拼接起来,返回字符串:

std::string
CheckoutRecord::getQueueMember(const size_t index){
	return wait_list[index]->first + "\t" + wait_list[index]->second;
	
}

不过这是封装过得了,不能当左值被改变了

必须有const版本,不然getQueueMember(1) = "asd";还能执行,不过没有任何效果,误导

const std::string& 
CheckoutRecord::getQueueMember const(const size_t index) const{//这个也不对,返回的是对临时string的引用,因为是重载(const引起的重载),也不阻止给返回值的赋值操作
	return wait_list[index]->first + "\t" + wait_list[index]->second;
	
}


const std::string
CheckoutRecord::getQueueMember(const size_t index) const{//只定义一个它就对了,不要重载,这属于封装了,不是下标操作符了,就需要无法改变
	return wait_list[index]->first + "\t" + wait_list[index]->second;
	
}
pe14_19.cpp:86:29: error: passing ‘const std::string’ as ‘this’ argument of 
‘std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const _CharT*) 
[with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>,
 std::basic_string<_CharT, _Traits, _Alloc> = std::basic_string<char>]’ discards qualifiers







你可能感兴趣的:(C++,Date,String,list,vector,pair)