// chapter-14.cpp : 重载运算符和类型转换(operator int()()const)
//
#include "stdafx.h"
#include<iostream>
#include<string>
#include<map>
#include<set>
#include<functional>
#include<algorithm>
#include<numeric>
using namespace std;
class Example_operator
{
public:
Example_operator() = default;
Example_operator(const string &s, const map<string, set<string>> &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<string, set<string>> 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<string> 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<int>强制转换!若为条件,则同样允许自动转换!
{
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<Type> minus multiplies divides modulus negate
//关系:equal_to not_equal_to greater greater_equal less less_equal
//逻辑:logical_and logical_or logical_ not
//plus<int> intadd;int sum=intadd(3,4)
//函数、函数指针、lambda表达式、bind创建对象、重载运算符,均为可调用对象!可调用对象也有类型,为调用形式!int(int,int),接受2个int,返回一个int!
//使用function储存可调用对象,定义在头文件functional中!
//function<T> f; f是一个储存可调用对象!
//function<T> f(nullptr)
//function<T> f(obj)
//f 将f作为条件,当f含有一个可调用对象为真!
//f(args) 调用f中的对象,参数为args
//result_type 返回可调用对象返回的类型
//argument_type 返回实参类型!
//first_argument_type
//second_argument_type
// function<int(int, int)> f1 = add; 函数指针
// function<int(int, int)> f2 = divide(); 函数对象
function<int(int, int)> f3 = [](int i, int j) {return i*j; };
//map<string,function<int(int,int)>> 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<int>(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<则应该有其他比较关系,逻辑和关系返回布尔值,算术返回类类型,赋值返回左侧对象的引用!
//具有对称性的运算符应该定义为非成员函数!如算术、相等、关系和位运算符!;复合赋值运算符应该是成员函数!
chapter-14
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 回应!互动,团队,共情。青松岭~赶车万山大叔。 戚继光~选兵,正经史,浙江金华工人阶级,矿工,长剑剑法。农民阶级,...
- 01 几个月前,跟妈视频时她冷不丁地说:“小邵的妈妈去世了。”而我也冷不丁地愣住了。 小邵是我的小学同学,和我同住...