注意事项:有些必须是成员函数,比如,下标操作,赋值操作,有些最好不是,比如对称的比较==
自定义操作符至少要满足基本需要:
比如在关联容器中的键类型需要<,在顺序容器也应该定义==和<,sort算法需要<,find算法需要==
BTW,很多操作最好对应出现,比如
+对应+=;
==对应!=;
>对应 >= <= <;
Q1:如果不定义,有些操作符没意义,比如赋值,取地址和逗号操作符,但是Sales_item没定义operator&,却可以取地址。
Q2:重新定义&&和||操作符将失去短路特性,短路特性是怎么来的?就是实现里加上if语句,如果false就return了?--估计是!
//类定义
//自加运算操作符定义
Sales_item Sales_item::operator++(int){
//只是写个(int)做样子来平息operatorOverload.cpp:24:21: error: no ‘operator++(int)’ declared for postfix ‘++’
std::cout << "test: " << i << std::endl;
Sales_item item(*this);//还要相应加一个复制构造函数
this->units_sold += 1;
this->revenue += 1;//这是假定单个利润1了,多卖一个item,多一块钱利润
return item;//返回一个原来的副本,改变对象自身
}
//测试代码
std::cout << (item1++) << std::endl;//operatorOverload.cpp:24:21: error: no ‘operator++(int)’ declared for postfix ‘++’
std::cout << (item1++) << std::endl;//item1++怎么需要操作符operator++(int)呢,哪有int?调用这句的时候自动产生了?
//参数列表使用(int i)和(int i = 4)默认实参是没多大意义的。打印输出测试显示i都是0;
但是也不能无参Sales_item Sales_item::operator++(){}
默认实参应该是那样写吧
IO操作符重载
IO操作符因为要给每个对象成员单独进行IO操作,所以要声明友元。
注意输入和输出的const设置不一样。
double avg_price() const{return revenue / units_sold;} //operatorIO.cpp:21:39: error: passing ‘const Sales_item’ as ‘this’ argument of ‘double Sales_item::avg_price()’ discards qualifiers//不加const会出错,因为传递的是const对象(this一定const?怎么规定的?)。qualifier是限定符,例如const //反例:set(int a){this.a = a;}如果操作符是成员函数
item << cout;//和正常用法相反
为了和常规保持一致,IO操作符必须为非成员函数
不过也可以自己搞些个性的,因为实现是自己定义的。
比如item >> cout;//不过这不叫重载了吧,最起码不是original overload,是把>>输入操作符重载成>>输出操作符
//编写输入输出操作符,歪曲原来的功能,拿来玩玩,正常情况下不允许,不易用~! #include"head.h" class Sales_item{ public: Sales_item(const std::string &book): isbn(book), units_sold(1), revenue(3.0) { } // Sales_item(std::istream &is) { is >> *this; }//副作用1:原来的>>被占用,不能cin利用这种方法初始化对象了,不过可以把另一边也反过来 Sales_item(const Sales_item& item): isbn(item.isbn), units_sold(item.units_sold), revenue(item.revenue) {} friend std::ostream& operator<<(std::ostream&, const Sales_item&); std::ostream& operator>>(std::ostream&); public: double avg_price() const{return revenue / units_sold;}//不加const会出错,因为传递的是const对象 //operatorIO.cpp:21:39: error: passing ‘const Sales_item’ as ‘this’ argument of ‘double Sales_item::avg_price()’ discards qualifiers private: std::string isbn; unsigned units_sold; double revenue; }; std::ostream& operator<<(std::ostream& out, const Sales_item &s){ out << s.isbn << "\t" << s.units_sold << "\t" << s.revenue << "\t" << s.avg_price(); return out; } std::ostream& Sales_item::operator>>(std::ostream& out){ out << isbn << "\t" << units_sold << "\t" << revenue << "\t" << avg_price(); return out; } int main(){ Sales_item item1("hello"); std::cout << item1 << std::endl; item1 >> std::cout; std::endl >> item1 >> std::cout;//error:副作用2:必须以类对象为左操作数,前边不能加endl了,相对前一句不是完全翻转 }
14.7//为下面的类顶一个一个输出操作符, //赶时间啊,最后那个排队那个太复杂,不弄了,在初始化列表弄不了,应该在构造函数体内初始化它 //还有Date类,没有默认的,应该从c的time.h弄吧? #include"head.h" class CheckoutRecord{ public: 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 /*<< "\t第一个排队者" << (*check.wait_list.begin())->first << "\t" << (*check.wait_list.begin())->second*/ << "\t" << std::endl; return out; } int main(){ CheckoutRecord check1; std::cout << check1 << std::endl; }