C++ Primer 学习笔记 第十四章 重载运算与类型转换

C++ Primer 学习笔记 第十四章 重载运算与类型转换

494 重载sales_data的输出运算符

#include <string>
#include <iostream>
using namespace std;

class Sales_data {
    friend ostream &operator<<(ostream &, const Sales_data &item);

public:
    Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ }
    Sales_data() : Sales_data("", 0, 0.0f){ }
    std::string isbn() const { return bookNo; }

private:
    inline double avg_price() const;
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};


inline double Sales_data::avg_price() const
{
    return units_sold ? revenue/units_sold : 0;
}


ostream &operator<<(ostream &os, const Sales_data &item){
    os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
    return os;
}


int main(){
    Sales_data data("abc", 2, 4);
    cout << data << endl;
	// abc 2 8 4
    return 0;
}

成员函数版本的重载<< 不推荐

#include <string>
#include <iostream>
using namespace std;

class Sales_data {

public:
    Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ }
    Sales_data() : Sales_data("", 0, 0.0f){ }
    std::string isbn() const { return bookNo; }
    ostream &operator<<(ostream&);

private:
    inline double avg_price() const;
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};


inline double Sales_data::avg_price() const
{
    return units_sold ? revenue/units_sold : 0;
}


ostream & Sales_data::operator<<(ostream &os) {
    os << this->isbn() << " " << this->units_sold << " " << this->revenue << " " << this->avg_price();
    return os;
}


int main(){
    Sales_data data("abc", 2, 4);
    data << cout;
    // abc 2 8 4

    return 0;
}

495 重载输入运算符

#include <string>
#include <iostream>
using namespace std;

class Sales_data {
    friend ostream &operator<<(ostream &, Sales_data&);
    friend istream &operator>>(istream &, Sales_data &);

public:
    Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ }
    Sales_data() : Sales_data("", 0, 0.0f){ }
    std::string isbn() const { return bookNo; }

private:
    inline double avg_price() const;
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};


inline double Sales_data::avg_price() const
{
    return units_sold ? revenue/units_sold : 0;
}


ostream &operator<<(ostream &os, Sales_data& data){
    os << data.bookNo << " " << data.units_sold << " " << data.revenue << " " << data.avg_price();
    return os;
}

istream &operator>>(istream &is, Sales_data &item){
    double price;
    is >> item.bookNo >> item.units_sold >> price;
    if (is)
        item.revenue = item.units_sold*price;
    else
        item = Sales_data();
    return is;
}


int main(){
    Sales_data data("abc", 2, 4);
    cout << data << endl;
    // abc 2 8 4

    cout << "please enter bookNo, units_sold, price: " << endl;
    cin >> data;
    cout << data;


    return 0;
}

497 重写+=和+

Sales_data& Sales_data::operator+=(const Sales_data &rhs) {
    units_sold += rhs.units_sold;
    revenue += rhs.revenue;
    return *this;
}


Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs){
    Sales_data sum = lhs;
    sum += rhs;
    return sum;
}

499 运算符重写综合实例

#include <string>
#include <iostream>
using namespace std;

class Sales_data {
    friend ostream &operator<<(ostream &, Sales_data&);
    friend istream &operator>>(istream &, Sales_data &);
    friend bool operator==(const Sales_data&, const Sales_data&);
    friend bool operator!=(const Sales_data&, const Sales_data&);

public:
    Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ }
    Sales_data() : Sales_data("", 0, 0.0f){ }
    std::string isbn() const { return bookNo; }
    Sales_data& operator+=(const Sales_data &rhs);

private:
    inline double avg_price() const;
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};


inline double Sales_data::avg_price() const
{
    return units_sold ? revenue/units_sold : 0;
}


ostream &operator<<(ostream &os, Sales_data& data){
    os << data.bookNo << " " << data.units_sold << " " << data.revenue << " " << data.avg_price();
    return os;
}

istream &operator>>(istream &is, Sales_data &item){
    double price;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = item.units_sold*price;
    return is;
}

Sales_data& Sales_data::operator+=(const Sales_data &rhs) {
    units_sold += rhs.units_sold;
    revenue += rhs.revenue;
    return *this;
}


Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs){
    Sales_data sum = lhs;
    sum += rhs;
    return sum;
}

bool operator==(const Sales_data& lhs, const Sales_data& rhs){
    return lhs.isbn()==rhs.isbn() && lhs.units_sold==rhs.units_sold && lhs.revenue==rhs.revenue;
}

bool operator!=(const Sales_data &lhs, const Sales_data &rhs){
    return !(lhs==rhs);
}


int main(){
    Sales_data data("abc", 2, 4);
    cout << data << endl;
    // abc 2 8 4

//    cout << "please enter bookNo, units_sold, price: " << endl;
//    cin >> data;
//    cout << data;

    Sales_data data2("efg", 3, 5);
    Sales_data data3 = data + data2;
    cout << data3;

    return 0;
}

501 下标运算符

    string& operator[](size_t n){return elements[n];};
    const string& operator[](size_t n) const{return elements[n];};

503 前置和后置版本的++

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
using namespace std;


class StrBlob{
public:
    friend class StrBlobPtr;
    StrBlobPtr begin();
    StrBlobPtr end();

    typedef std::vector<std::string>::size_type size_type;
    StrBlob();
    StrBlob(std::initializer_list<std::string> il);

    size_type size() const {return data->size();};
    bool empty() const {return data->empty();};

    void push_back(const std::string &t){data->push_back(t);};
    void pop_back();

    std::string& front();
    std::string& back();
    std::shared_ptr<std::vector<std::string>> data;

private:
    void check(size_type i, const std::string &msg) const;
};


StrBlob::StrBlob() :data(make_shared<vector<string>>()){}
StrBlob::StrBlob(initializer_list<string> il):data(make_shared<vector<string>>(il)){}
void StrBlob::check(size_type i, const std::string &msg) const {
    if (i>=data->size())
        throw out_of_range(msg);
}

string& StrBlob::front() {
    check(0, "front on empty StrBlob");
    return data->front();
}
string& StrBlob::back() {
    check(0, "back on empty StrBlob");
    return data->back();
}
void StrBlob::pop_back() {
    check(0, "pop_back on empty StrBlob");
    data->pop_back();
}

class StrBlobPtr{
public:
    StrBlobPtr():curr(0){}
    StrBlobPtr(StrBlob &a, size_t sz=0):wptr(a.data), curr(sz){}
    string& deref() const;
    StrBlobPtr& incr();
    // front ++
    StrBlobPtr operator++();
    // back ++
    StrBlobPtr operator++(int);

private:
    shared_ptr<vector<string>> check(size_t, const string&) const;
    weak_ptr<vector<string>> wptr;
    size_t curr;
};

//shared_ptr<vector<string>>;
shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string &msg) const {
    auto ret = wptr.lock();
    if (!ret){
        throw runtime_error("unbound StrBlobPtr");
    }
    if (i>=ret->size())
        throw out_of_range(msg);
    return ret;
}

string& StrBlobPtr::deref() const {
    auto p = check(curr, "dereference past end");
    return (*p)[curr];
}

StrBlobPtr& StrBlobPtr::incr() {
    check(curr, "increment past end of StrBlobPtr");
    ++curr;
    return *this;
}

StrBlobPtr StrBlob::begin(){
    return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end(){
    return StrBlobPtr(*this, data->size());
}

StrBlobPtr StrBlobPtr::operator++() {
    check(curr, "increment past end ofStrBlobPtr");
    ++curr;
    return *this;
}

StrBlobPtr StrBlobPtr::operator++(int) {
    StrBlobPtr ret = *this;
    ++*this;
    return ret;
}



int main() {
    StrBlob stb;
    StrBlobPtr stbr(stb);

    vector<string> vec = {"a", "b", "c"};
    for (string text:vec){
        stb.push_back(text);
    }

    auto begin = stb.begin();
    auto end = stb.end();


    stbr++;
    ++stbr;


    while(true){

        try{
            cout <<stbr.deref() << endl;
            stbr.incr();
        } catch (...) {
            cout << "end of data" << endl;
            break;
        }

    }

    return 0;
}

504 重写解引用运算符

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
using namespace std;


class StrBlob{
public:
    friend class StrBlobPtr;
    StrBlobPtr begin();
    StrBlobPtr end();

    typedef std::vector<std::string>::size_type size_type;
    StrBlob();
    StrBlob(std::initializer_list<std::string> il);

    size_type size() const {return data->size();};
    bool empty() const {return data->empty();};

    void push_back(const std::string &t){data->push_back(t);};
    void pop_back();

    std::string& front();
    std::string& back();
    std::shared_ptr<std::vector<std::string>> data;

private:
    void check(size_type i, const std::string &msg) const;
};


StrBlob::StrBlob() :data(make_shared<vector<string>>()){}
StrBlob::StrBlob(initializer_list<string> il):data(make_shared<vector<string>>(il)){}
void StrBlob::check(size_type i, const std::string &msg) const {
    if (i>=data->size())
        throw out_of_range(msg);
}

string& StrBlob::front() {
    check(0, "front on empty StrBlob");
    return data->front();
}
string& StrBlob::back() {
    check(0, "back on empty StrBlob");
    return data->back();
}
void StrBlob::pop_back() {
    check(0, "pop_back on empty StrBlob");
    data->pop_back();
}

class StrBlobPtr{
public:
    StrBlobPtr():curr(0){}
    StrBlobPtr(StrBlob &a, size_t sz=0):wptr(a.data), curr(sz){}
    string& deref() const;
    StrBlobPtr& incr();
    // front ++
    StrBlobPtr operator++();
    // back ++
    StrBlobPtr operator++(int);
    StrBlobPtr operator--();

    string& operator*() const{
        auto p = check(curr, "dereference past end");
        cout << "curr: " << curr << endl;
        return (*p)[curr];
    }



private:
    shared_ptr<vector<string>> check(size_t, const string&) const;
    weak_ptr<vector<string>> wptr;
    size_t curr;
};

//shared_ptr<vector<string>>;
shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string &msg) const {
    auto ret = wptr.lock();
    if (!ret){
        throw runtime_error("unbound StrBlobPtr");
    }
    if (i>=ret->size())
        throw out_of_range(msg);
    return ret;
}

string& StrBlobPtr::deref() const {
    auto p = check(curr, "dereference past end");
    return (*p)[curr];
}

StrBlobPtr& StrBlobPtr::incr() {
    check(curr, "increment past end of StrBlobPtr");
    ++curr;
    return *this;
}

StrBlobPtr StrBlob::begin(){
    return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end(){
    return StrBlobPtr(*this, data->size());
}

StrBlobPtr StrBlobPtr::operator++() {
    check(curr, "increment past end ofStrBlobPtr");
    ++curr;
    return *this;
}

StrBlobPtr StrBlobPtr::operator++(int) {
    StrBlobPtr ret = *this;
    ++*this;
    return ret;
}

StrBlobPtr StrBlobPtr::operator--() {
    check(curr, "increment past end ofStrBlobPtr");
    --curr;
    return *this;
}


int main() {
    StrBlob a1 = {"hi", "bye", "now"};
    StrBlobPtr p(a1);
    *p = "okay";
    cout << *p << endl; // okay
    cout << *(++p) << endl; // bye



    return 0;
}

506 重写调用运算符

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
using namespace std;


struct absInt{
    int operator() (int val) const {
        return val < 0 ? -val:val;
    }
};


int main() {
    int i = -42;
    absInt absObj;
    cout << absObj(i) << endl;

    return 0;
}

507 重载运算符和for_each结合使用

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
using namespace std;


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;
};


int main() {
    PrintString printer;
    string s = "hello world";
    printer(s);  // hello world
    cout << endl;

    PrintString errors(cerr, '\n');
    errors(s); // helloword\n
    cout << endl;

    vector<string> vs = {"a", "b", "c"};
    for_each(vs.begin(), vs.end(), errors);

    return 0;
}

508 类对象和lambda函数的互换

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
using namespace std;


class ShorterString{
public:
    bool operator()(const string &s1, const string &s2) const {
        return s1.size() < s2.size();
    }
};

bool compare(const string &s1, const string &s2){
    return s1.size() < s2.size();
}



int main() {

    vector<string> words = {"a", "abcd", "ab", "abc"};
//    stable_sort(words.begin(), words.end(),
//                [](const string &a, const string &b){return a.size()<b.size();});

//    stable_sort(words.begin(), words.end(), compare);

    stable_sort(words.begin(), words.end(), ShorterString());

    ostream_iterator<string> out_iter(cout, " ");
    copy(words.begin(), words.end(), out_iter);


    return 0;
}
    

508 类对象代替lambda捕获参数

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
using namespace std;



void elimDups(vector<string> &words){
    sort(words.begin(), words.end());
    auto unqi = unique(words.begin(), words.end());
    words.erase(unqi, words.end());
}

class SizeComp{
public:
    SizeComp(size_t n):sz(n){}
    bool operator()(const string &s) const{
        return s.size() >= sz;
    }
private:
    size_t sz;

};


void biggies(vector<string> &words, vector<string>::size_type sz){
    elimDups(words);
    stable_sort(words.begin(), words.end(), [](const string &a, const string &b){return a.size()<b.size();});

    for (auto val:words){
        cout << val << " ";
    }
    cout << endl;
    // fox red the over slow jumps quick turtle

//    auto wc = find_if(words.begin(), words.end(), [sz](const string &a){return a.size()>=sz;});
    auto wc = find_if(words.begin(), words.end(), SizeComp(sz));
    auto count = words.end() - wc;
    cout << count << endl; // 5  5 elements with length >=4

    for_each(wc, words.end(),[](const string &s){cout << s << " ";});
    cout << endl;
    // over slow jumps quick turtle

}




int main() {

    vector<string> vec= {"the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle"};
    biggies(vec, 4);
}

510 使用标准库函数对象

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
using namespace std;



bool compare(const int *a, const int *b){
    return *a < *b;
}


int main() {
    plus<int> intAdd;
    negate<int>intNegate;
    int sum = intAdd(10, 20);
    cout << sum << endl; // 30
    sum = intNegate(intAdd(10, 20));
    cout << sum << endl; // -30


    vector<int> nums = {1, 3, 2, 6, 5, 4};
    vector<int *> p_nums;
    for (auto iter=nums.begin(); iter!=nums.end(); ++iter){
        p_nums.push_back(&*iter);
    }


//    sort(p_nums.begin(), p_nums.end(), [](string *a, string *b){return (*a)<(*b);});

//    sort(p_nums.begin(), p_nums.end(), less<int*>());
    sort(p_nums.begin(), p_nums.end(), compare);

    for (auto iter=p_nums.begin(); iter!=p_nums.end(); ++iter){
        cout << **iter << " ";
    }
    cout << endl; // 1 2 3 4 5 6

}


512 可调用对象与function

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;

int add(int a, int b){
    return a+b;
}

class divide{
public:
    int operator()(int a, int b){return a/b;};
};


int main() {

    function<int(int, int)> f1 = add;
    function<int(int, int)> f2 = divide();
    function<int(int, int)> f3 = [](int i, int j){return i*j;};

    cout << f1(4, 2) << endl; //6
    cout << f2(4, 2) << endl; //2
    cout << f3(4, 2) << endl; //8
    
}

513 function结合map构造计算器

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;

int add(int a, int b){
    return a+b;
}

class divide{
public:
    int operator()(int a, int b){return a/b;};
};

auto mod = [](int i, int j){return i%j;};


int main() {

    map<string, function<int(int, int)>> binops ={
            {"+", add},
            {"-", minus<int>()},
            {"/", divide()},
            {"*", [](int i, int j){return i*j;}},
    };

    cout<< binops["+"](10, 5) << endl;
    
}


514 类型转换运算符

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;

class SmallInt{
public:
    SmallInt(int i=0, int j=0):val(i){
        if(i<0||i>255){
            throw out_of_range("Bad SmallInt value");
        }
    }
    operator int() const{return val;};

    size_t val;
};


int main() {
    SmallInt si;
    si = 4;
    cout << si.val << endl; // 4
    cout << si+3 << endl; // 7

    si = 3.14;
    cout << si.val << endl; // 3

    cout << si+3.14 << endl; // 6.14

}

516 类类型显式转换运算符

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;

class SmallInt{
    friend ostream& operator<<(ostream &, const SmallInt &);
public:
    SmallInt(int n=0):val(n){}


    explicit operator int() const{
        return val;
    }

private:
    size_t val;

};


ostream& operator<<(ostream &os, const SmallInt &item){
    os << item.val;
    return os;
}

int main() {
    SmallInt si;
    si = 4;
    cout << si << endl;
    // error
//    si + 3;
    // ok because of explicit conversion
    cout << static_cast<int>(si) + 3 << endl; //7

}

14.47 类方法两个不同的const的区别

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;


struct Integral{
    Integral(int n=0):val(n){

    }

    operator const int(){
        cout << "operator const int()" << endl;
        val = 6;
        return val;
    };
    operator int() const{
        cout << "operator int() const" << endl;
//        val = 6
        return 4;
    };

    int val;

};


int main() {
    Integral itg;
    const Integral itg2;
    itg = 3;  //constructor
    int i = itg;  // operator const int()
    int j = itg2; // operator int() const
}

520 避免二义性

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;


struct C{
    C(int){};
};

struct D{
    D(int){};
};

void manip(const C&){

}
void manip(const D&){

}

int main() {
    // ambiguous
    manip(10);

    manip(C(10));

}

14.51

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;


struct LongDouble{
    LongDouble(double = 0.0){cout << "constructor" << endl;};
    operator double(){return 2;};
    operator float(){return 4;};
};

void calc(int){};
void calc(LongDouble){};


int main() {
    LongDouble ldObj;
    float ex2 = ldObj; //double

    double dval=5;
    calc(dval); // constructor

}

522 算术类型转换和重载运算符的二义性

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;


class SmallInt{
    friend SmallInt operator+(const SmallInt&, const SmallInt&);

public:
    SmallInt(int n =0):val(n){};
    operator int() const{return val;}

    size_t val;
};

SmallInt operator+(const SmallInt& a, const SmallInt& b){
    SmallInt res;
    res.val = a.val + b.val;
    return res;
}


int main() {
    SmallInt s1(1), s2(2);
    SmallInt s3 = s1 + s2;
    cout << s3.val << endl;
    // ambiguous
//    int i = s3 + 0;

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值