// chapter-14.cpp : 重载运算符和类型转换(operator int()()const) // #include "stdafx.h" #include #include #include #include #include #include #include using namespace std; class Example_operator { public: Example_operator() = default; Example_operator(const string &s, const map> &m) :id(s), information(m) {} friend ostream& operator<<(ostream &os,const Example_operator &rhs); friend istream& operator>>(istream &in, Example_operator &rhs); Example_operator operator+=(const Example_operator &rhs); friend Example_operator operator+(const Example_operator &lhs, const Example_operator &rhs); friend bool operator==(const Example_operator &lhs, const Example_operator &rhs); friend bool operator!=(const Example_operator &lhs, const Example_operator &rhs); private: string id; map> information; //void read_from_input(); }; //输入输出运算符,必须是非成员函数。const引用,不改变内容节省时间! ostream& operator<<(ostream &os, const Example_operator &rhs) { os << rhs.id <<":"<< endl; for (auto &r : rhs.information) { cout << "\b" << r.first << " : "; for (auto &&rs : r.second) { cout << rs << " "; } cout << endl; } return os; } istream& operator>>(istream &in, Example_operator &rhs) { cout << "Please input the name:" << endl; in >> rhs.id; cout << "Please input something(keys value ...(; to stop!)),or q to quit..." << endl; if (in) //检查输入是否成功!输入运算符必须检查输入失败,而输出则不需要! //当出现输入错误是,最好是自己使用IO标准库来表示这些错误! { string key, value; while (cin >> key) { if (key == "q") break; else { set tmp_set; while (cin >> value) { if (value == ";") break; tmp_set.insert(value); } rhs.information[key] = tmp_set; } } } return in; } Example_operator Example_operator::operator+=(const Example_operator &rhs) { Example_operator &sum = *this; if (sum.id == rhs.id) { for (auto &r : sum.information) { for (auto &k : rhs.information) { if (r.first == k.first) { r.second.insert(k.second.cbegin(), k.second.cend()); } else { sum.information.insert(k); } } } } return sum; } Example_operator operator+(const Example_operator &lhs, const Example_operator &rhs) { Example_operator sum = lhs; if (sum.id == rhs.id) { sum += rhs; } return sum; } bool operator==(const Example_operator &lhs, const Example_operator &rhs) { return (lhs.id == rhs.id && lhs.information == rhs.information); } bool operator!=(const Example_operator &lhs, const Example_operator &rhs) { return !(lhs == rhs); } class PrintString //如果类定义了函数调用运算符,就可以像函数一样使用该对象! { public: PrintString(ostream &o = cout, char c = ' ') :os(o), sep(c) {} void operator()(const string &s) const { os << s << sep; } private: ostream &os; char sep; }; class SmallInt//构造函数将算术类型的值转换成smallInt对象,而类型转换运算符将smallInt对象转换成int! { public: SmallInt(int i = 0) :val(i) { if (i < 0 || i>255) throw out_of_range("Bad smallint value!"); } operator int()const { return val; }//类型转换!(包含数组指针和函数指针) private: size_t val; }; class SmallInt_Explicit//显示类型转换,必须使用static_cast强制转换!若为条件,则同样允许自动转换! { public: SmallInt_Explicit(int i = 0) :val(i) { if (i < 0 || i>255) throw out_of_range("Bad smallint value!"); } explicit operator int()const { return val; }//定义类型转换! private: size_t val; }; int main() { Example_operator stu01("xiaoming", { { "grade",{ "99" } },{ "car",{ "baoma" } } }); cout << stu01 << endl; Example_operator stu02; cin >> stu02; cout << stu02 << endl; cout << (stu01 + stu02) << endl; PrintString printer; printer("abc"); //for_each(v.begin(),v.end(),printer(cout,'\n'))!;lambda是函数对象,编译器编译成一个未命名类的未命名对象!如果含有值捕获,则对应类将建有对应的数据成员! //标准库自带函数对象,定义在头文件functional中。主要应用于泛型算法中! //算术:plus minus multiplies divides modulus negate //关系:equal_to not_equal_to greater greater_equal less less_equal //逻辑:logical_and logical_or logical_ not //plus intadd;int sum=intadd(3,4) //函数、函数指针、lambda表达式、bind创建对象、重载运算符,均为可调用对象!可调用对象也有类型,为调用形式!int(int,int),接受2个int,返回一个int! //使用function储存可调用对象,定义在头文件functional中! //function f; f是一个储存可调用对象! //function f(nullptr) //function f(obj) //f 将f作为条件,当f含有一个可调用对象为真! //f(args) 调用f中的对象,参数为args //result_type 返回可调用对象返回的类型 //argument_type 返回实参类型! //first_argument_type //second_argument_type // function f1 = add; 函数指针 // function f2 = divide(); 函数对象 function f3 = [](int i, int j) {return i*j; }; //map> binops={{"+",add}}; //传入重载函数时,为了避免二义性,1、int (*fp)(int,int)=add;2、lambad //自定义类型转换,返回类型必须能作为函数的返回类型!(数组和函数不能返回,但其指针可以) SmallInt si; si = 4; //转为size_t cout << si + 3 << endl; //size_t转为int,再执行整数的加法! //实际中很少定义类型转换符,但是定义向bool的类型转换还是比较普遍的现象! //为避免隐式类型转换引发错误结果,进行显示的类型转换运算符定义! SmallInt_Explicit sie = 3; cout << static_cast(sie) + 4 << endl; //当表达式被用作条件,显示类型转换会被隐式的执行! //避免二义性类型转换:1、f(b)=A(b)和b.operator(A),避免同时定义相同的类型转换!(构造函数和成员函数、同类避免即转int,又转double)2、除了转换为bool,应该避免定义类型转换! return 0; } //为自定义类对象定义重载运算符,有利于编写和阅读!(内置类型无法重载!) //除了operator()外,其他重载运算符不能有默认实参!??? //不能重载的运算符《:: .* . ?:》/可以重载的运算符《+ - * /(算术) &(比较) <<(IO) [](下标) ()(函数调用运算符 int operator()(int val) const{returnval<0?-val:val}) -> &&(逻辑) new》 //重载运算符应该与内置类型一致,有operator==则应该有operator!=,有operator<则应该有其他比较关系,逻辑和关系返回布尔值,算术返回类类型,赋值返回左侧对象的引用! //具有对称性的运算符应该定义为非成员函数!如算术、相等、关系和位运算符!;复合赋值运算符应该是成员函数!