有个稍微特殊的容器成员,定义从输入到输出,到下标等的一系列操作符
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; }
//定义下标操作符,下标操作符要考虑返回的是个左值,被赋值的情况,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()对比一下就型了把
要不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