• cppPrimer学习14th


    cppPrimer学习14th

    从章节14.8开始看

    14.1

    在什么情况下重载的运算符与内置运算符有所区别?在什么情况下重载的运算符又与内置运算符一样?
    
    不同点:
    重载运算符 至少有一个参数为类
    重载运算符的求值顺序不一定相同,比如 && || 会依次求值
    
    相同点:
    	优先级和结核性相同
    

    14.2

    // 为Sales_data 重载输入,输出,加法和复合赋值
    // 为Sales_data 重载输入,输出,加法和复合赋值
    #include <iostream>
    #include <string>
    
    //using namespace std;
    using std::cin;
    using std::cout;
    using std::endl;
    using std::istream;
    using std::ostream;
    using std::string;
    
    class Sales_data
    {
        friend ostream &operator<<(ostream &o, const Sales_data &d);
        friend istream &operator>>(istream &o, Sales_data &d);
        friend Sales_data operator+(Sales_data &a, Sales_data &b);
    
    public:
        Sales_data(const string &bookNo, unsigned units, double revenue) : bookNo(bookNo), units_sold(units), revenue(revenue)
        {
        }
        Sales_data() : bookNo("default id"), units_sold(0), revenue(0) {}
        Sales_data &operator+=(const Sales_data &b)
        {
            units_sold += b.units_sold;
            revenue += b.revenue;
        }
    
    private:
        std::string bookNo;      // name
        unsigned units_sold = 0; //售卖的数量
        double revenue = 0.0;    //售卖的总价
        double GetAvg() const
        {
            return units_sold ? revenue / units_sold : 0;
        }
    };
    
    ostream &operator<<(ostream &o, const Sales_data &d)
    {
        o << d.bookNo << ": " << d.units_sold << "," << d.revenue << "," << d.GetAvg() << endl;
    }
    
    istream &operator>>(istream &o, Sales_data &d)
    {
        cout << "pls input bookNo ,units_sold, revenue" << endl;
        o >> d.bookNo >> d.units_sold >> d.revenue;
        if (!o)
            d = Sales_data();
    }
    Sales_data operator+(Sales_data &a, Sales_data &b)
    {
        return Sales_data(a.bookNo, a.units_sold + b.units_sold, a.revenue + b.revenue);
    }
    
    int main(int argc, char const *argv[])
    {
        Sales_data book1("ID1001", 10, 38);
        cout << book1 << endl;
    
        Sales_data book2("ID1002", 10, 40);
        cout << book2 << endl;
    
        Sales_data book3 = book1 + book2;
        cout << book3 << endl;
    
        book3 += book2;
        cout << book3 << endl;
    
        cin >> book1;
        cout << book1 << endl;
    
        while (1)
            ;
        return 0;
    }
    
    

    14.3

    string和vector都定义了重载的==以比较各自的对象,
        假设svec1和svec2是存放string的vector,确定在下面的表达式中分别使用了哪个版本的==?
    (a) "cobble" == "stone"     这里比较的是 char*
    (b) svec1[0] ==svec2[0]     string
    (c) svec1 ==svec2           vector
    (d) svec[0] == "stone"      string
    

    14.4

    如何确定下列运算符是否应该是类的成员?
    
    (a) %     非
    (b) %=    是
    (c) ++    是 
    (d) ->    是 
    (e) <<    非 
    (f) &&    非 
    (g) ==    是  
    (h) ()    是
    

    14.5

    /*
    14.5 在7.5.1节的练习7.40中,编写了下列类中的某一个框架,请问在这个类中应该定义重载的运算符吗?如果是,请写出来。
         (a)Book    (b)Date    (c)Employee    (d)Vehicle    (e)Object    (f)Tree
    */
    
    #include <iostream>
    #include <iomanip>
    class Date
    {
    private:
        int year = 2000;
        int month = 1;
        int day = 1;
        int hour = 0;
        int min = 0;
        int sec = 0;
    
    public:
        Date(int y, int m, int d, int h, int mi, int s) : year(y), month(m), day(d), hour(h), min(mi), sec(s) {}
        friend std::ostream &operator<<(std::ostream &o, Date &d);
    };
    
    std::ostream &operator<<(std::ostream &o, Date &d)
    {
        return o << d.year << "-" << d.month << "-" << d.day << " " << d.hour << ":" << d.min << ":" << d.sec;
    }
    
    int main(int argc, const char **argv)
    {
    
        Date d(2020, 4, 9, 14, 17, 5);
        std::cout << d << std::endl;
        while (1)
            ;
        return 0;
    }
    
    

    14.6

    参考14.2
    

    14.7

    class String
    {
    public:
    	String();
    	String(const char *str);
    	friend ostream& operator<<(ostream &os, const String &str);
    private:
    	char *str;
    };
     
    ostream& operator<<(ostream &os, const String &str)
    {
    	cout << str;
    	return os;
    }
    

    14.8

    参考14.5
    

    14.9

    参考14.2
    

    14.10

    a 正常构造
    b 默认构造
    

    14.11

    price 可能未定义
    

    14.12

    /*
    14.12 你在7.5.1节的练习中曾经选择并编写了一个类,为它定义一个输入运算符并确保该运算符可以处理输入错误。
    14.5 在7.5.1节的练习7.40中,编写了下列类中的某一个框架,请问在这个类中应该定义重载的运算符吗?如果是,请写出来。
         (a)Book    (b)Date    (c)Employee    (d)Vehicle    (e)Object    (f)Tree
    */
    
    #include <iostream>
    #include <iomanip>
    class Date
    {
    private:
        int year = 2000;
        int month = 1;
        int day = 1;
        int hour = 0;
        int min = 0;
        int sec = 0;
    
    public:
        Date() = default;
        Date(int y, int m, int d, int h, int mi, int s) : year(y), month(m), day(d), hour(h), min(mi), sec(s) {}
        friend std::ostream &operator<<(std::ostream &o, Date &d);
        friend std::istream &operator>>(std::istream &i, Date &d);
    };
    
    std::ostream &operator<<(std::ostream &o, Date &d)
    {
        return o << d.year << "-" << d.month << "-" << d.day << " " << d.hour << ":" << d.min << ":" << d.sec;
    }
    
    std::istream &operator>>(std::istream &o, Date &ret)
    {
        Date d;
        if (o >> d.year >> d.month >> d.day >> d.hour >> d.min >> d.sec)
        {
            ret = d;
        }
        else
        {
            ret = Date();
            o.clear();
            o.sync();
        }
    }
    
    int main(int argc, const char **argv)
    {
    
        Date d(2020, 4, 9, 14, 17, 5);
        std::cout << d << std::endl;
    
        while (1)
        {
            std::cout << "pls input date" << std::endl;
            std::cin >> d;
            std::cout << d << std::endl;
        }
    
        while (1)
            ;
        return 0;
    }
    
    

    14.13

    减法
    Sales_data operator-(Sales_data &a, Sales_data &b)
    {
        return Sales_data(a.bookNo, a.units_sold - b.units_sold, a.revenue - b.revenue);
    }
    
    
    Sales_data &operator-=(const Sales_data &b)
    {
        units_sold -= b.units_sold;
        revenue -= b.revenue;
    }
    

    14.14

    你觉得为什么调用operator+=来定义operator+比其他方法要更有效?
    
    性能上没有优势,而可读性上后者显然更好。
    

    14.17

    /*
    14.17 重载== 和 !=
    14.12 你在7.5.1节的练习中曾经选择并编写了一个类,为它定义一个输入运算符并确保该运算符可以处理输入错误。
    14.5 在7.5.1节的练习7.40中,编写了下列类中的某一个框架,请问在这个类中应该定义重载的运算符吗?如果是,请写出来。
         (a)Book    (b)Date    (c)Employee    (d)Vehicle    (e)Object    (f)Tree
    */
    
    #include <iostream>
    #include <iomanip>
    class Date
    {
    private:
        int year = 2000;
        int month = 1;
        int day = 1;
        int hour = 0;
        int min = 0;
        int sec = 0;
    
    public:
        friend std::ostream &operator<<(std::ostream &o, Date &d);
        friend std::istream &operator>>(std::istream &i, Date &d);
        friend bool operator!=(const Date &t, const Date &d);
        friend bool operator==(const Date &t, const Date &d);
        Date() = default;
        Date(int y, int m, int d, int h, int mi, int s) : year(y), month(m), day(d), hour(h), min(mi), sec(s) {}
    };
    
    std::ostream &operator<<(std::ostream &o, Date &d)
    {
        return o << d.year << "-" << d.month << "-" << d.day << " " << d.hour << ":" << d.min << ":" << d.sec;
    }
    
    std::istream &operator>>(std::istream &o, Date &ret)
    {
        Date d;
        if (o >> d.year >> d.month >> d.day >> d.hour >> d.min >> d.sec)
        {
            ret = d;
        }
        else
        {
            ret = Date();
            o.clear();
            o.sync();
        }
    }
    
    bool operator==(const Date &t, const Date &d)
    {
        return t.year == d.year && t.month == d.month && t.day == d.day && t.hour == d.hour && t.min == d.min && t.sec == d.sec;
    }
    bool operator!=(const Date &t, const Date &d)
    {
        return !(t == d);
    }
    int main(int argc, const char **argv)
    {
    
        Date a(2020, 4, 9, 14, 17, 5);
        std::cout << a << std::endl;
    
        Date b(2020, 1, 9, 14, 17, 5);
        std::cout << b << std::endl;
    
        std::cout << std::boolalpha << (a == b) << std::endl;
        std::cout << std::boolalpha << (a != b) << std::endl;
    
        // while (1)
        // {
        //     std::cout << "pls input date" << std::endl;
        //     std::cin >> d;
        //     std::cout << d << std::endl;
        // }
    
        while (1)
            ;
        return 0;
    }
    
    

    14.19

    /*
    14.19 你在7.5.1节的练习7.40中曾经选择并编写了一个类,你认为它应该含有关系运算符吗?如果是,请实现它;如果不是,解释原因
    
    14.17 重载== 和 !=
    14.12 你在7.5.1节的练习中曾经选择并编写了一个类,为它定义一个输入运算符并确保该运算符可以处理输入错误。
    14.5 在7.5.1节的练习7.40中,编写了下列类中的某一个框架,请问在这个类中应该定义重载的运算符吗?如果是,请写出来。
         (a)Book    (b)Date    (c)Employee    (d)Vehicle    (e)Object    (f)Tree
    */
    
    #include <iostream>
    #include <iomanip>
    class Date
    {
    private:
        int year = 2000;
        int month = 1;
        int day = 1;
        int hour = 0;
        int min = 0;
        int sec = 0;
    
    public:
        friend std::ostream &operator<<(std::ostream &o, Date &d);
        friend std::istream &operator>>(std::istream &i, Date &d);
        friend bool operator!=(const Date &t, const Date &d);
        friend bool operator==(const Date &t, const Date &d);
    
        friend bool operator>(const Date &t, const Date &d);
        friend bool operator>=(const Date &t, const Date &d);
        friend bool operator<(const Date &t, const Date &d);
        friend bool operator<=(const Date &t, const Date &d);
        Date() = default;
        Date(int y, int m, int d, int h, int mi, int s) : year(y), month(m), day(d), hour(h), min(mi), sec(s) {}
    };
    
    std::ostream &operator<<(std::ostream &o, Date &d)
    {
        return o << d.year << "-" << d.month << "-" << d.day << " " << d.hour << ":" << d.min << ":" << d.sec;
    }
    
    std::istream &operator>>(std::istream &o, Date &ret)
    {
        Date d;
        if (o >> d.year >> d.month >> d.day >> d.hour >> d.min >> d.sec)
        {
            ret = d;
        }
        else
        {
            ret = Date();
            o.clear();
            o.sync();
        }
    }
    
    bool operator==(const Date &t, const Date &d)
    {
        return t.year == d.year && t.month == d.month && t.day == d.day && t.hour == d.hour && t.min == d.min && t.sec == d.sec;
    }
    bool operator!=(const Date &t, const Date &d)
    {
        return !(t == d);
    }
    
    bool operator>(const Date &t, const Date &d)
    {
        return ((t.year > d.year) ||
                (t.year == d.year && t.month > d.month) ||
                (t.year == d.year && t.month == d.month && t.day > d.day) ||
                (t.year == d.year && t.month == d.month && t.day == d.day && t.hour > d.hour) ||
                (t.year == d.year && t.month == d.month && t.day == d.day && t.hour == d.hour && t.min > d.min) ||
                (t.year == d.year && t.month == d.month && t.day == d.day && t.hour == d.hour && t.min == d.min && t.min > d.min));
    }
    bool operator>=(const Date &t, const Date &d)
    {
        return t > d || t == d;
    }
    bool operator<(const Date &t, const Date &d)
    {
        return !(t >= d);
    }
    bool operator<=(const Date &t, const Date &d)
    {
        return !(t > d);
    }
    
    int main(int argc, const char **argv)
    {
    
        Date a(2020, 4, 9, 14, 17, 1);
        Date b(2020, 4, 9, 14, 17, 2);
    
        std::cout << std::boolalpha << (a > b) << std::endl;
        std::cout << std::boolalpha << (a >= b) << std::endl;
        std::cout << std::boolalpha << (a < b) << std::endl;
        std::cout << std::boolalpha << (a <= b) << std::endl;
        std::cout << std::boolalpha << (a >= a) << std::endl;
        std::cout << std::boolalpha << (a < a) << std::endl;
    
        // while (1)
        // {
        //     std::cout << "pls input date" << std::endl;
        //     std::cin >> d;
        //     std::cout << d << std::endl;
        // }
    
        while (1)
            ;
        return 0;
    }
     
    

    14.20

    14.21

    += 执行加法,+调用+= 的优势在于好看一点
    
    // + 调用 +=
    // Sales_data operator+(Sales_data &a, Sales_data &b)
    // {
    //     //return Sales_data(a.bookNo, a.units_sold + b.units_sold, a.revenue + b.revenue);
    //     Sales_data t = a;
    //     t += b;
    //     return t;
    // }
    // Sales_data &Sales_data::operator+=(const Sales_data &b)
    // {
    //     units_sold += b.units_sold;
    //     revenue += b.revenue;
    //     return *this;
    // }
    
    // += 调用+
    Sales_data operator+(const Sales_data &a, const Sales_data &b)
    {
        Sales_data t = a;
        t.units_sold += b.units_sold;
        t.revenue += b.revenue;
        return t;
    }
    Sales_data &Sales_data::operator+=(const Sales_data &b)
    {
        *this = *this + b;
        return *this;
    }
    

    14.22

    /*
    14.22:定义赋值运算符的一个新版本,使得我们能把一个表示ISBN的string赋给一个Sales_data对象
    */
    Sales_data &operator=(const std::string &s)
    {
        bookNo = s;
        return *this;
    }
    

    14.23

    //14.23:为你的StrVec类定义一个initializer_list赋值运算符
    StrVec &StrVec::operator=(initializer_list<string> li)
    {
        auto data = allc_n_copy(li.begin(), li.end());
        free();
        elements = data.first;
        first_free = cap = data.second;
        return *this;
    }
    

    14.24

    // 14.24:你在7.5.1节的7.40中曾经选择并编写了一个类,你认为它应该含有拷贝赋值和移动赋值运算符吗?
    // 如果是,请实现它们
    date 不需要,没有指针相关的
    

    14.25

    //14.25上题的这个类还需要定义其他赋值运算符吗?如果是,请实现它们;同时说明运算对象应该是什么类型并解释原因
    // string > date
    Date &Date::operator=(const std::string &s)
    {
        std::istringstream in(s);
        in >> *this;
        return *this;
    }
    

    14.29

    为什么不定义const版本的递增和递减运算符
    因为会改变对象的值
    

    14.33

    一个重载的函数调用运算符应该接受几个运算对象
    0个或者多个,和普通函数一样,上限这个不去细究
    

    14.34

    //定义一个函数对象类,令其执行if-then-else的操作:该类的调用运算符接受三个形参,
    //它首先检查第一个形参,如果成功返回第二个形参的值,如果不成功返回第三个形参的值
    struct ifelsethen
    {
    	int operator(bool flag,int a,int b)
    	{
    	 return flag? a:b;
    	}
    	
    }
    

    14.35

    14.36

    /*
    14.36 保存到vector
    14.35 编写一个类似PrintString的类,令其从istream中读取一行输入,然后返回一个表示我们所读内容的string。如果读取失败,返回空string
    */
    
    #include <iostream>
    #include <string>
    #include <vector>
    
    class PrintStringLine
    {
    public:
        std::string operator()(std::istream &in)
        {
            std::string line;
            if (getline(in, line))
                return line;
            else
                return std::string();
        }
    };
    
    int main(int argc, char const *argv[])
    {
        PrintStringLine p;
        //std::cout << "--" << p(std::cin) << "--" std::endl;
    
        std::vector<std::string> v;
        // v.push_back(p(std::cin));
        // v.push_back(p(std::cin));
        // v.push_back(p(std::cin));
        // v.push_back(p(std::cin));
        // v.push_back(p(std::cin));
    
        for (std::string tmp; !(tmp = PrintStringLine()(std::cin)).empty();)
            v.push_back(tmp);
    
        for (auto ch : v)
            std::cout << "~" << ch << "~" << std::endl;
    
        while (1)
            ;
        return 0;
    }
    
    

    14.37

    
    /*
    14.37 编写一个类令其检查两个值是否相等。使用该对象及标准库算法编写程序,令其替换某个序列中具有给定值的所有实例
    */
    #include <vector>
    #include <algorithm>
    #include <iostream>
    
    class Equal
    {
    private:
        int data;
    
    public:
        Equal(int c) : data(c) {}
        bool operator()(int a) { return a == data; }
    };
    
    int main(int argc, char const *argv[])
    {
        std::vector<int> v = {1, 2, 3, 4, 5, 6, 2, 3, 2, 1, 4, 6, 7, 8, 1, 2, 3, 1};
        std::replace_if(v.begin(), v.end(), Equal(1), 9999);
    
        // for (auto ch : v)
        //     std::cout << ch << ",";
        // std::cout << std::endl;
    
        std::for_each(v.begin(), v.end(), [](std::vector<int>::value_type c) { std::cout << c << ","; });
        //std::for_each(v.begin(), v.end(), [](int c) { std::cout << c << ","; });
    
        while (1)
        {
            /* code */
        }
    
        return 0;
    }
    
    

    14.38

    14.39

    /*
    14.39 修改其报告1~9的单词有几个,10以上的有几个
    14.38 编写一个类令其检查某个给定的string对象的长度是否与一个阀值相等。使用该对象编写程序,统计并报告在输入的文件中长度为1的单词有多少个、长度为2的单词有多少个。
    */
    
    #include <string>
    #include <fstream>
    #include <iostream>
    #include <vector>
    class StrLen
    {
    private:
        int len;
        bool cmp;
    
    public:
        StrLen(int l, bool cmp = false) : len(l), cmp(cmp) {}
        bool operator()(const std::string &s)
        {
            if (cmp == false)
                return s.size() == len;
            else
                return s.size() >= len;
        }
    };
    
    int main(int argc, char const *argv[])
    {
        std::string path = "D:\1.txt";
        std::ifstream infile(path);
        if (!infile)
        {
            std::cout << "err to open path" << path << std::endl;
            while (1)
                ;
        }
    
        std::string s;
        std::vector<std::string> v;
        int len_1 = 0, len_2 = 0, len_10_big = 0, len_10_lit = 0;
        StrLen l2(2);
        StrLen l1(1);
        StrLen l10(10, true);
    
        while (infile >> s)
        {
            //v.push_back(std::move(s));
            if (l1(s))
                len_1++;
    
            if (l2(s))
                len_2++;
            if (l10(s))
                len_10_big++;
            else
                len_10_lit++;
        }
        std::cout << "len=1,count=" << len_1 << std::endl;
        std::cout << "len=2,count=" << len_2 << std::endl;
        std::cout << "len>=10,count=" << len_10_big << std::endl;
        std::cout << "len<10>,count=" << len_10_lit << std::endl;
        while (1)
            ;
    
        return 0;
    }
    
    

    14.40

    /*
    14.40 重写10.3.2的P349 的biggies 函数,使用可调用类替换lambda
    */
    
    #include <string>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    using std::cin;
    using std::cout;
    using std::endl;
    using std::find_if;
    using std::for_each;
    using std::sort;
    using std::stable_sort;
    using std::string;
    using std::vector;
    
    class WordsABSizeCmp
    {
    public:
        bool operator()(const string &a, const string &b)
        {
            return a.size() < b.size();
        }
    };
    
    class WordsBigThan
    {
    private:
        int default_size;
    
    public:
        WordsBigThan(int dsize) : default_size(dsize) {}
        bool operator()(const string &a)
        {
            return a.size() >= default_size;
        }
    };
    
    void elimdups(vector<string> &words)
    {
        sort(words.begin(), words.end());
        auto end_unique = unique(words.begin(), words.end());
        words.erase(end_unique, words.end());
    }
    
    string make_plural(size_t ctr, string const &word, string const &ending)
    {
        return (ctr > 1) ? word + ending : word;
    }
    
    class PrintString
    {
    private:
        std::ostream &o;
    
    public:
        PrintString(std::ostream &o = std::cout) : o(o) {}
        std::ostream &operator()(const string &s) { return o << s << ","; }
    };
    
    void biggies(vector<string> &words, vector<string>::size_type sz)
    {
        // 删除重复单词
        elimdups(words);
        // 按照长度排序单词
        stable_sort(words.begin(), words.end(), WordsABSizeCmp());
        // 找到第一个size大于某值的元素
        auto wc = find_if(words.begin(), words.end(), WordsBigThan(sz));
        // 计算size大于某值的数目
        auto count = words.end() - wc;
    
        cout << count << make_plural(count, "word", "s") << " of length " << sz << "or longer" << endl;
        for_each(wc, words.end(), PrintString());
    }
    
    int main()
    {
        vector<string> vec{"fox", "jumps", "over", "quick", "red",
                           "red", "slow", "the", "turtle"};
        biggies(vec, 4);
        while (1)
        {
            /* code */
        }
    }
    

    14.41

    你认为C++11新标准为什么要增加lambda?对于你自己来说,什么情况下会使用lambda,什么情况下会使用类?
        lambda 适合短小功能,不会反复复用
        类,反复复用,功能多
    

    14.42

    (a)统计大于1024的值有多少个。
    std::count_if(i.cbegin(),i.cend(),std::bind(std::greater<int>(),_1,1024));
    
    (b)找到第一个不等于pooh的字符串。
    std::find_if(i.cbegin(),i.cend(),std::bind(std::not_equal_to<string>(),_1,"pooh"));
    
    (c)将所有的值乘以2.
    std::transform(i.begin(),i.end(),i.begin(),bind(std::multiplies<int>(),_1,2));
    

    14.43

    /*
    14.43:使用标准库函数对象判断一个给定的int值是否能被int容器中的所有元素整除
    */
    
    #include <algorithm>
    #include <iostream>
    #include <vector>
    #include <functional>
    using namespace std::placeholders;
    
    bool IfDivVec(int a, std::vector<int> &v)
    {
        auto w = std::find_if(v.cbegin(), v.cend(), std::bind(std::modulus<int>(), _1, a));
        return w == v.cend();
    }
    
    int main(int argc, char const *argv[])
    {
        int a = 3;
        std::vector<int> v = {3, 6, 9, 18, 24};
        std::cout << std::boolalpha << IfDivVec(a, v) << std::endl;
    
        v.push_back(13);
        std::cout << std::boolalpha << IfDivVec(a, v) << std::endl;
        while (1)
            ;
    
        return 0;
    }
    
    // auto data = {2, 3, 4, 5};
    // int input;
    // std::cin >> input;
    // std::modulus<int> mod;
    // auto predicator = [&](int i) { return 0 == mod(input, i); };
    // auto is_divisible = std::any_of(data.begin(), data.end(), predicator);
    // std::cout << (is_divisible ? "Yes!" : "No!") << std::endl;
    
    

    14.45

    14.45 编写类型转换运算符转换 Sales_data 到 string 和double
        
    operator const string() { return bookNo; }
    operator const double() { return GetAvg(); }
    
    int main(int argc, char const *argv[])
    {
        Sales_data book1("ID1001", 10, 38);
        cout << book1 << endl;
    
        cout << static_cast<string>(book1) << endl;
        cout << static_cast<double>(book1) << endl;
        while (1)
            ;
        return 0;
    }
    

    14.46

    14.46 你认为应该定义上述两种类型转换吗 ?  是否要定义成 explicit?
    
    	不应该,转换的含义不明确,应该作为具体的成员函数
    	如果定义了,应该定义成 explicit 否则cout<<xxx 这类操作不知道怎么操作而且含义不精确
    
    

    14.47

    struct Integral
    {
    	operator const int();			返回值不能改变
    	operator int() const;			不会改变类对象的内容
    };
    

    14.48

    14.49

    TODO

    14.50

    // 可能用到哪些类类型的转换序列呢?说明初始化是否正确并解释原因
    struct LongDouble {
    	LongDouble(double = 0.0);
    	operator double();
    	operator float();
    };
    
    LongDouble ldObj;		
    int ex1 = ldObj;	// float 或者 double  二义性
    float ex2 ldObj;	// 调用operator float();
    

    14.51

    在调用calc的过程中,可能用到哪些类型转换序列呢?说明最佳可行函数是如何选拔出来的。
    
    void calc(int);
    void calc(LongDouble);
    
    double dval;
    calc(dval);		//调用calc(int)  因为doube转int是标准类型转换
    

    14.52

    14.52 在下面的加法表达式中分别选用了哪个operator?
    		列出候选函数、可行函数及为每个可行函数的实参执行的类型转换
    		
    		
    struct longDouble {
    	//用于演示的成员operator+; 在通常情况下+s是个非成员
    	longDouble operator+(const SmallInt&);
    	//其他成员与14.9.2节一致
    };
    longDouble operator+(longDouble&, double);
    
    
    SmallInt si;
    longDouble ld;
    
    ld = si + ld;	//没有转换的
    
    
    ld = ld + si;
    // 二义性
    // 非成员 operator+ ,  >>> int转double
    // 成员 operator+(const SmallInt&)   完全匹配的
    		
    

    14.53

    14.53:假设我们已经定义了如第522页所示的SmallInt,判断下面的加法表达式是否合法。
           如果合法,使用了哪个加法运算符?如果不合法,应该怎样修改代码才能使其合法?
    
    SamllInt sl;
    
    double d = s1 + 3.14;
    // 1. 非成员函数 double转SamllInt 也就是构造函数  SamllInt(int)  ===> double>int
    // 2.  SamllInt 转double 赋值
    
    // 1. s1转int, 
    // 2. int 提升到 double
    
    SmallInt s1;
    double d = s1 + SmallInt(3.14);
    

    StrBlob StrBlobPtr Strvec String

    strblob.h

    #ifndef __STR_BLOB_H__
    #define __STR_BLOB_H__
    
    #include <vector>
    #include <memory>
    #include <iostream>
    #include <initializer_list>
    #include <exception>
    
    using std::cout;
    using std::endl;
    using std::initializer_list;
    using std::make_shared;
    using std::ostream;
    using std::shared_ptr;
    using std::string;
    using std::vector;
    
    class StrBlobPtr;
    class ConstStrBlobPtr;
    /**
     * @brief vector<string>
     * 
     */
    class StrBlob
    {
        using size_type = vector<string>::size_type;
        friend std::ostream &operator<<(std::ostream &o, const StrBlob &s);
        friend bool operator==(const StrBlob &, const StrBlob &);
        friend bool operator!=(const StrBlob &, const StrBlob &);
        friend bool operator<(const StrBlob &, const StrBlob &);
        friend bool operator>(const StrBlob &, const StrBlob &);
        friend bool operator<=(const StrBlob &, const StrBlob &);
        friend bool operator>=(const StrBlob &, const StrBlob &);
    
        friend class StrBlobPtr;
        friend class ConstStrBlobPtr;
    
    private:
        shared_ptr<vector<string>>
            data;
        void check(size_type at, const string err_message) const;
    
    public:
        StrBlob() : data(make_shared<vector<string>>()) {}
        StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {}
        // 拷贝构造,拷贝赋值,移动构造,移动赋值
        StrBlob(const StrBlob &s) : data(make_shared<vector<string>>(*s.data)) {}
        StrBlob &operator=(const StrBlob &s);
        StrBlob(StrBlob &&s) noexcept : data(std::move(s.data)) {}
        StrBlob &operator=(StrBlob &&s);
    
        void push_back(const string &s) { data->push_back(s); }
        void push_back(string &&s) { data->push_back(std::move(s)); }
        void pop_back();
        string &front();
        string &back();
        const string &front() const;
        const string &back() const;
        string &operator[](size_t at);
        const string &operator[](size_t at) const;
    
        // 迭代器相关的
        StrBlobPtr begin();       // { return StrBlobPtr(*this); }
        StrBlobPtr end();         //{ return StrBlobPtr(*this, data->size()); }
        ConstStrBlobPtr cbegin(); // { return StrBlobPtr(*this); }
        ConstStrBlobPtr cend();   //{ return StrBlobPtr(*this, data->size()); }
    
        size_type size() const { return data->size(); }
    };
    
    inline StrBlob &StrBlob::operator=(const StrBlob &s)
    {
        data = make_shared<vector<string>>(*s.data);
        return *this;
    }
    
    inline StrBlob &StrBlob::operator=(StrBlob &&s)
    {
        if (this != &s)
        {
            data = s.data;
            s.data = nullptr;
        }
        return *this;
    }
    
    inline void StrBlob::check(size_type at, const string err_message) const
    {
        if (at >= data->size())
            throw std::out_of_range(err_message);
    }
    
    inline void StrBlob::pop_back()
    {
        check(0, "try to pop empty vector!!!");
        data->pop_back();
    }
    
    inline string &StrBlob::front()
    {
        check(0, "try to get front empty vector!!!");
        return data->front();
    }
    
    inline string &StrBlob::back()
    {
        check(0, "try to get back empty vector!!!");
        return data->back();
    }
    inline const string &StrBlob::front() const
    {
        check(0, "try to get front empty vector!!!");
        return data->front();
    }
    
    inline const string &StrBlob::back() const
    {
        check(0, "try to get back empty vector!!!");
        return data->back();
    }
    
    inline string &StrBlob::operator[](size_t at)
    {
        check(at, "out of range!!!");
        return data->at(at);
    }
    inline const string &StrBlob::operator[](size_t at) const
    {
        check(at, "out of range!!!");
        return data->at(at);
    }
    
    /**
     * @brief vector<string> iterator
     * 
     */
    class StrBlobPtr
    {
        friend bool operator==(const StrBlobPtr &, const StrBlobPtr &);
        friend bool operator!=(const StrBlobPtr &, const StrBlobPtr &);
        friend bool operator<(const StrBlobPtr &, const StrBlobPtr &);
        friend bool operator>(const StrBlobPtr &, const StrBlobPtr &);
        friend bool operator<=(const StrBlobPtr &, const StrBlobPtr &);
        friend bool operator>=(const StrBlobPtr &, const StrBlobPtr &);
    
    private:
        std::weak_ptr<vector<string>> wptr;
        // convert weak_ptr to shared_ptr
        shared_ptr<vector<string>> check(size_t at, string err_msg) const;
        size_t curr;
    
    public:
        StrBlobPtr() : curr(0) {}
        StrBlobPtr(StrBlob &s, size_t at = 0) : wptr(s.data), curr(at) {}
    
        StrBlobPtr &operator++();
        StrBlobPtr &operator--();
        // 后置版本返回的是原来的值的拷贝,再++,所以不能返回引用
        StrBlobPtr operator++(int);
        StrBlobPtr operator--(int);
        StrBlobPtr &operator+=(int);
        StrBlobPtr &operator-=(int);
        StrBlobPtr operator+(int) const;
        StrBlobPtr operator-(int) const;
        string &operator[](size_t);
        const string &operator[](size_t) const;
        string &operator*();
        const string &operator*() const;
    
        // 迭代器指向string 那么 *it 是string 而 it-> 自然是string的操作了
        string *operator->();
        const string *operator->() const;
    };
    inline shared_ptr<vector<string>> StrBlobPtr::check(size_t at, string err_msg) const
    {
        auto ret = wptr.lock();
        if (!ret)
            throw std::runtime_error("No shared_ptr get!!!");
        if (at > ret->size()) //because of at==ret->size when iterator arrive the end
            throw std::out_of_range("out of range to check StrBlobPtr of" + err_msg);
        return ret;
    }
    inline StrBlobPtr &StrBlobPtr::operator++()
    {
        ++curr;
        check(curr, "err to ++ ");
        return *this;
    }
    inline StrBlobPtr &StrBlobPtr::operator--()
    {
        --curr;
        check(curr, "err to -- ");
        return *this;
    }
    inline StrBlobPtr StrBlobPtr::operator++(int)
    {
        StrBlobPtr ret = *this;
        ++*this;
        return ret;
    }
    inline StrBlobPtr StrBlobPtr::operator--(int)
    {
        StrBlobPtr ret = *this;
        --*this;
        return ret;
    }
    inline StrBlobPtr &StrBlobPtr::operator+=(int offset)
    {
        curr += offset;
        check(curr, "err to += ");
        return *this;
    }
    inline StrBlobPtr &StrBlobPtr::operator-=(int offset)
    {
        curr -= offset;
        check(curr, "err to -= ");
        return *this;
    }
    
    inline StrBlobPtr StrBlobPtr::operator+(int offset) const
    {
        StrBlobPtr ret = *this;
        ret += offset;
        return *this;
    }
    inline StrBlobPtr StrBlobPtr::operator-(int offset) const
    {
        StrBlobPtr ret = *this;
        ret -= offset;
        return *this;
    }
    inline string &StrBlobPtr::operator[](size_t offset)
    {
        auto ret = check(offset, "Get [] err");
        return (*ret)[offset];
    }
    inline const string &StrBlobPtr::operator[](size_t offset) const
    {
        auto ret = check(offset, "Get [] err");
        return (*ret)[offset];
    }
    
    inline string &StrBlobPtr::operator*()
    {
        //auto ret = check(curr, "Get [] err");
        //return ret->at(curr);
        return (*this)[curr];
    }
    inline const string &StrBlobPtr::operator*() const
    {
        return (*this)[curr];
    }
    
    // 迭代器指向string 那么 *it 是string 而 it-> 自然是string的操作了
    inline string *StrBlobPtr::operator->()
    {
        return &(this->operator*());
    }
    inline const string *StrBlobPtr::operator->() const
    {
        return &(this->operator*());
    }
    
    // 个人觉得应该是 非const的迭代器继承自const的迭代器 const_iterator
    // --这里的const 是指不能通过该迭代器修改指向的内容
    /**
     * @brief vector<string> iterator
     * 
     */
    class ConstStrBlobPtr
    {
        friend bool operator==(const ConstStrBlobPtr &, const ConstStrBlobPtr &);
        friend bool operator!=(const ConstStrBlobPtr &, const ConstStrBlobPtr &);
        friend bool operator<(const ConstStrBlobPtr &, const ConstStrBlobPtr &);
        friend bool operator>(const ConstStrBlobPtr &, const ConstStrBlobPtr &);
        friend bool operator<=(const ConstStrBlobPtr &, const ConstStrBlobPtr &);
        friend bool operator>=(const ConstStrBlobPtr &, const ConstStrBlobPtr &);
    
    private:
        std::weak_ptr<vector<string>> wptr;
        // convert weak_ptr to shared_ptr
        shared_ptr<vector<string>> check(size_t at, string err_msg) const;
        size_t curr;
    
    public:
        ConstStrBlobPtr() : curr(0) {}
        ConstStrBlobPtr(const StrBlob &s, size_t at = 0) : wptr(s.data), curr(at) {}
    
        ConstStrBlobPtr &operator++();
        ConstStrBlobPtr &operator--();
        // 后置版本返回的是原来的值的拷贝,再++,所以不能返回引用
        ConstStrBlobPtr operator++(int);
        ConstStrBlobPtr operator--(int);
        ConstStrBlobPtr &operator+=(int);
        ConstStrBlobPtr &operator-=(int);
        ConstStrBlobPtr operator+(int) const;
        ConstStrBlobPtr operator-(int) const;
        //string &operator[](size_t); --这里的const 是指不能通过该迭代器修改指向的内容
        const string &operator[](size_t) const;
        //string &operator*();
        const string &operator*() const;
        //string *operator->();  --这里的const 是指不能通过该迭代器修改指向的内容
        const string *operator->() const;
    };
    inline shared_ptr<vector<string>> ConstStrBlobPtr::check(size_t at, string err_msg) const
    {
        auto ret = wptr.lock();
        if (!ret)
            throw std::runtime_error("No shared_ptr get!!!");
        if (at > ret->size()) //because of at==ret->size when iterator arrive the end
            throw std::out_of_range("out of range to check ConstStrBlobPtr of" + err_msg);
        return ret;
    }
    inline ConstStrBlobPtr &ConstStrBlobPtr::operator++()
    {
        ++curr;
        check(curr, "err to ++ ");
        return *this;
    }
    inline ConstStrBlobPtr &ConstStrBlobPtr::operator--()
    {
        --curr;
        check(curr, "err to -- ");
        return *this;
    }
    inline ConstStrBlobPtr ConstStrBlobPtr::operator++(int)
    {
        ConstStrBlobPtr ret = *this;
        ++*this;
        return ret;
    }
    inline ConstStrBlobPtr ConstStrBlobPtr::operator--(int)
    {
        ConstStrBlobPtr ret = *this;
        --*this;
        return ret;
    }
    inline ConstStrBlobPtr &ConstStrBlobPtr::operator+=(int offset)
    {
        curr += offset;
        check(curr, "err to += ");
        return *this;
    }
    inline ConstStrBlobPtr &ConstStrBlobPtr::operator-=(int offset)
    {
        curr -= offset;
        check(curr, "err to -= ");
        return *this;
    }
    
    inline ConstStrBlobPtr ConstStrBlobPtr::operator+(int offset) const
    {
        ConstStrBlobPtr ret = *this;
        ret += offset;
        return *this;
    }
    inline ConstStrBlobPtr ConstStrBlobPtr::operator-(int offset) const
    {
        ConstStrBlobPtr ret = *this;
        ret -= offset;
        return *this;
    }
    // inline string &ConstStrBlobPtr::operator[](size_t offset)
    // {
    //     auto ret = check(offset, "Get [] err");
    //     return (*ret)[offset];
    // }
    inline const string &ConstStrBlobPtr::operator[](size_t offset) const
    {
        auto ret = check(offset, "Get [] err");
        return (*ret)[offset];
    }
    
    // inline string &ConstStrBlobPtr::operator*()
    // {
    //     //auto ret = check(curr, "Get [] err");
    //     //return ret->at(curr);
    //     return (*this)[curr];
    // }
    inline const string &ConstStrBlobPtr::operator*() const
    {
        return (*this)[curr];
    }
    
    // 迭代器指向string 那么 *it 是string 而 it-> 自然是string的操作了
    inline const string *ConstStrBlobPtr::operator->() const
    {
        return &(this->operator*());
    }
    
    #endif // !__STR_BLOB_H__
    
    

    strblob.cpp

    #include "StrBlob.h"
    //****************************************************************************
    std::ostream &operator<<(std::ostream &o, const StrBlob &s)
    {
        for (size_t i = 0; i != s.size(); i++)
            o << s[i] << ",";
        return o;
    }
    bool operator==(const StrBlob &a, const StrBlob &b)
    {
        return *a.data == *b.data;
    }
    bool operator!=(const StrBlob &a, const StrBlob &b)
    {
        return !(a == b);
    }
    bool operator<(const StrBlob &a, const StrBlob &b)
    {
        return std::lexicographical_compare(a.data->begin(), a.data->end(),
                                            b.data->begin(), b.data->end());
    }
    bool operator>(const StrBlob &a, const StrBlob &b)
    {
        return b < a;
    }
    bool operator<=(const StrBlob &a, const StrBlob &b)
    {
        return !(a > b);
    }
    bool operator>=(const StrBlob &a, const StrBlob &b)
    {
        return !(a < b);
    }
    
    StrBlobPtr StrBlob::begin()
    {
        return StrBlobPtr(*this);
    }
    StrBlobPtr StrBlob::end()
    {
        return StrBlobPtr(*this, data->size());
    }
    ConstStrBlobPtr StrBlob::cbegin()
    {
        return ConstStrBlobPtr(*this);
    }
    ConstStrBlobPtr StrBlob::cend()
    {
        return ConstStrBlobPtr(*this, data->size());
    }
    //****************************************************************************
    bool operator==(const StrBlobPtr &a, const StrBlobPtr &b)
    {
        return a.curr == b.curr;
    }
    bool operator!=(const StrBlobPtr &a, const StrBlobPtr &b)
    {
        return !(a == b);
    }
    bool operator<(const StrBlobPtr &a, const StrBlobPtr &b)
    {
        return (a.curr < b.curr);
    }
    bool operator>(const StrBlobPtr &a, const StrBlobPtr &b)
    {
        return (b < a);
    }
    bool operator<=(const StrBlobPtr &a, const StrBlobPtr &b)
    {
        return (b > a);
    }
    bool operator>=(const StrBlobPtr &a, const StrBlobPtr &b)
    {
        return (a < b);
    }
    //****************************************************************************
    bool operator==(const ConstStrBlobPtr &a, const ConstStrBlobPtr &b)
    {
        return a.curr == b.curr;
    }
    bool operator!=(const ConstStrBlobPtr &a, const ConstStrBlobPtr &b)
    {
        return !(a == b);
    }
    bool operator<(const ConstStrBlobPtr &a, const ConstStrBlobPtr &b)
    {
        return (a.curr < b.curr);
    }
    bool operator>(const ConstStrBlobPtr &a, const ConstStrBlobPtr &b)
    {
        return (b < a);
    }
    bool operator<=(const ConstStrBlobPtr &a, const ConstStrBlobPtr &b)
    {
        return (b > a);
    }
    bool operator>=(const ConstStrBlobPtr &a, const ConstStrBlobPtr &b)
    {
        return (a < b);
    }
    //****************************************************************************
    
    int main(int argc, char const *argv[])
    {
        try
        {
    
            StrBlob ls({"A", "B", "C"});
            ls.push_back("D");
            ls.pop_back();
            std::cout << ls.front() << std::endl;
            std::cout << ls.back() << std::endl;
            std::cout << ls << std::endl;
    
            StrBlob ls2({"A", "B", "C"});
            std::cout << std::boolalpha << (ls == ls2) << std::endl;
            ls2.push_back("D");
            std::cout << std::boolalpha << (ls <= ls2) << std::endl;
            //
            ls.push_back("E");
            std::cout << ls << std::endl;
            std::cout << ls2 << std::endl;
            std::cout << std::boolalpha << (ls2 > ls) << std::endl;
    
            std::cout << "-------------------------------------" << std::endl;
            std::cout << "-------------Test iterator-----------" << std::endl;
            std::cout << "-------------------------------------" << std::endl;
    
            for (auto i = ls.begin(); i != ls.end(); i++)
            {
                std::cout << *i << ",";
                std::cout << std::endl
                          << "size= " << i->size() << std::endl;
                *i = "(" + *i + ")";
            }
    
            for (auto i = ls.begin(); i != ls.end(); i++)
            {
                std::cout << *i << ",";
                std::cout << std::endl
                          << "size= " << i->size() << std::endl;
            }
    
            for (auto i = ls.cbegin(); i != ls.cend(); i++)
            {
                std::cout << *i << ",";
                std::cout << std::endl
                          << "size= " << i->size() << std::endl;
                //*i = "(" + *i + ")"; // does not match any in class
                // inline string &ConstStrBlobPtr::operator[](size_t offset)
                // 只有 const string
            }
    
            /* code */
        }
        catch (const std::exception &e)
        {
            std::cerr << e.what() << '
    ';
        }
        while (1)
            ;
        return 0;
    }
    
    
  • 相关阅读:
    集群--LVS的介绍
    http协议
    tomcat目录结构
    Response乱码的解决方法
    j2ee学习笔记 Filter过滤器
    Java数据库连接池
    j2ee学习笔记URLEncoder.encode(String , enc)处理特殊字符
    python学习笔记--Django入门四 管理站点--二
    网络学习笔记----02--IGMP组播、ARP
    网络学习笔记----01--pathping跟踪数据包路径
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/12679844.html
Copyright © 2020-2023  润新知