chapter-14

// 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<则应该有其他比较关系,逻辑和关系返回布尔值,算术返回类类型,赋值返回左侧对象的引用!
//具有对称性的运算符应该定义为非成员函数!如算术、相等、关系和位运算符!;复合赋值运算符应该是成员函数!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容