//错误 不能为int重定义内置运算符
int operator+(int, int);
当运算符作用于内置类型的运算对象时,我们无法改变运算符的含义。
只能重载已经有的运算符而不能发明新的符号。
//一个非成员运算符函数的等价调用
data1 + data2; //普通表达式
operator+(data1, data2); // 等价的函数调用
//显式调用成员运算函数
data1 += data2; //直接调用
data1.operator+=(data2); // 对运算符函数的等价调用
将this指针绑定到data1的地址,将data2作为实参传入了函数。
string s = "world";
string t = s + "!"; // 正确 我们把有个const char* 加到一个string对象中
string u = "hi" + s; //如果+是string的成员,则产生错误
上面的语句是否合法取决于经string重载的操作符“+”,s+"!",这个语句总是合法的,因为当+是内置重载的时候,改操作等价于s.operator+("!");该语句是合法的 ,当重载操作是非成员函数时,这条语句等价于 operator+(s,"!"),此时也是合法的。
"hi" + s;这条语句当是成员函数时,会发生错误 因为此这条语句相当于 "hi".operator+(s),而数据类型const char *并没有重载这个符号。
练习14.1 在什么情况下重载的运算符与内置的运算符有所区别?什么情况下重载的运算符又与内置运算符一样。
1. 当运算符为成员函数时,此时不能任意的调换位置。
2. 当运算符的实现和内置版本不一致时。
练习14.2 为Sales_data编写重载的输入、输出、加法和复合赋值运算符。
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Sales_data{
friend std::istream &read(std::istream&, Sales_data&);
friend std::istream &operator>>(istream &is, Sales_data&);
public:
Sales_data() = default;
Sales_data(const std::string &s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(p*n){}
Sales_data(const std::string &s) :bookNo(s){}
Sales_data(std::istream&);
std::string isbn() const { return bookNo; }
private:
double avg_price() const
{
return units_sold ? revenue / units_sold : 0;
}
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
Sales_data::Sales_data(std::istream& is){
read(is, *this);
}
istream &operator>>(std::istream& is, Sales_data& item){
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
istream &read(istream &is, Sales_data &item){
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
int _tmain(int argc, _TCHAR* argv[])
{
Sales_data a;
cin >> a;
return 0;
}
练习14.3 string和vector都定义了重载的==以比较各自的对象,假设svec1和svec2是存放string的vector, 确定在下面的表达式中分别使用了那个版本的==?
(a) "cobble" == "stone" (b) svec1[0] == svec2[0];
(c) svec1 == svec2 (d) svec1 == "stone"
答:(a)既没有用string的==操作,也没用vector的==操作。
(b)string的==操作
(c)用vector的==操作
(d)应该是要报错(确实是要报错 不存在从char * 向vector<string>的数据类型转换)
练习14.4:如何确定下列运算符是否应该是类的成员?
(a)% 是,此运算符与运算对象的前后关系有关
(b)%= 是
(c)++ 是
(d)-> 是
(e)<< 不是 因为该运算符cout出现在前面 如果设置成成员函数会改变使用规则
(f)&& 否 该运算符可以交换顺序,如果设置为成员函数就和原有含义不一样
(g)== 否
(h)() 否