zoukankan      html  css  js  c++  java
  • C++ Primer(第五版)第14章答案

    github项目地址

    目录

    14.01 14.02 14.03 14.04 14.05 14.06
    14.07 14.08 14.09 14.10 14.11 14.12
    14.13 14.14 14.15 14.16 14.17 14.18
    14.19 14.20 14.21 14.22 14.23 14.24
    14.25 14.26 14.27 14.28 14.29 14.30
    14.31 14.32 14.33 14.34 14.35 14.36
    14.37 14.38 14.39 14.40 14.41 14.42
    14.43 14.44 14.45 14.46 14.47 14.48
    14.49 14.50 14.51 14.52 14.53

    14.01

    在什么情况下重载的运算符与内置运算符有所区别?在什么情况下重载的运算符又与内置运算符一样?

    我们可以直接调用重载运算符函数,重载运算符和内置运算符具有相同的优先级和结合性。

    14.02|h|cpp

    Sales_data编写重载的输入、输出、加法和复合赋值运算符。

    Sales_data类的声明

    //
    // Created by wangheng on 2020/5/4.
    //
    
    #ifndef CPP_PRIMER_EX14_02_H
    #define CPP_PRIMER_EX14_02_H
    
    #include <string>
    #include <iostream>
    #include <utility>
    
    class Sales_data {
        friend std::istream& operator>>(std::istream&, Sales_data&);    // 输入
        friend std::ostream& operator<<(std::ostream&, Sales_data&);    // 输出
        friend Sales_data operator+(const Sales_data&, const Sales_data&);  // 加法
    public:
        Sales_data(std::string  s, unsigned n, double p) :
            bookNo(std::move(s)), units_sold(n), revenue(n * p){}
        Sales_data() : Sales_data("", 0, 0.0f) {}
        Sales_data(const std::string& s) : Sales_data(s, 0, 0.0f) {}
        Sales_data(std::istream& is);
    
        Sales_data& operator+=(const Sales_data&);  // 复合运算符
        std::string isbn() const {return bookNo;}
    
    private:
        inline double avg_price() const ;
    
        std::string bookNo;
        unsigned units_sold = 0;
        double revenue = 0.0;
    };
    
    std::istream& operator>>(std::istream&, Sales_data&);
    std::ostream& operator<<(std::ostream&, Sales_data&);
    Sales_data operator+(const Sales_data&, const Sales_data&);
    
    inline
    double Sales_data::avg_price() const {
        return units_sold ? revenue / units_sold : 0;
    }
    
    #endif //CPP_PRIMER_EX14_02_H
    

    Sales_data类的实现

    //
    // Created by wangheng on 2020/5/4.
    //
    
    #include "ex14_02.h"
    
    Sales_data::Sales_data(std::istream &is) {
        is >> *this;
    }
    
    Sales_data& Sales_data::operator+=(const Sales_data &rhs) {
        units_sold += rhs.units_sold;
        revenue += rhs.revenue;
        return *this;
    }
    
    std::istream& operator>>(std::istream& is, Sales_data& item) {
        double price = 0.0;
        is >> item.bookNo >> item.units_sold >> price;
        if (is) {
            item.revenue = price * item.units_sold;
        } else {
            item = Sales_data();
        }
        return is;
    }
    
    std::ostream& operator<<(std::ostream& os, Sales_data& item) {
        os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
        return os;
    }
    
    Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs) {
        Sales_data sum = lhs;
        sum += rhs;
        return sum;
    }
    
    int main() {
        Sales_data item1(std::cin);
        Sales_data item2("2", 3, 3.4);
        Sales_data sum = item1 + item2;
        std::cout << sum << std::endl;
    
        return 0;
    }
    

    14.03

    stringvector都定义了重载的==以比较各自的对象,假设svec1svec2是存放stringvector,确定在下面的表达式中分别使用了哪个版本的==

    (a)"coblle" == "stone" (b)svec1[0] == svec2[0]

    (c)svec1 == svec2 (d)svec1[0] == "stone"

    (a)都不是,(b)使用了string版的==,(c)使用了vector版的==,(d)使用了string版的==

    14.04

    如何确定下列运算符是否应该是类的成员?

    (a) %
    (b) %=
    (c) ++
    (d) ->
    (e) <<
    (f) &&
    (g) ==
    (h) ()
    
    • (a)不需要是成员
    • (b)是成员
    • (c)是成员
    • (d)必须是成员
    • (e)不能是成员
    • (f)不需要是成员
    • (g)不需要是成员
    • (h)必须是成员

    14.05

    在7.5.1节的练习7.40(第261页)中,编写了下列类中某一个的框架,请问在这个类张应该定义重载的运算符吗?如果是,请写出来。

    (a) Book
    (b) Date
    (c) Employee
    (d) Vehicle
    (e) Object
    (f) Tree
    

    Book需要定义重载的运算符。

    h|cpp|test

    book.h

    //
    // Created by wangheng on 2020/5/5.
    //
    
    #ifndef CPP_PRIMER_EX14_05_H
    #define CPP_PRIMER_EX14_05_H
    
    #include <iostream>
    #include <string>
    
    class Book {
        friend std::istream& operator>>(std::istream&, Book&);
        friend std::ostream& operator<<(std::ostream&, const Book&);
        friend bool operator==(const Book&, const Book&);
        friend bool operator!=(const Book&, const Book&);
    
    public:
        Book() = default;
        Book(unsigned no, std::string name, std::string author, std::string pubDate) :
            no(no), name(name), author(author), pubDate(pubDate) {}
        Book(std::istream& in) {in >> *this;}
    
    private:
        unsigned no;
        std::string name;
        std::string author;
        std::string pubDate;
    };
    
    std::istream& operator>>(std::istream&, Book&);
    std::ostream& operator<<(std::ostream&, const Book&);
    bool operator==(const Book&, const Book&);
    bool operator!=(const Book&, const  Book&);
    
    #endif //CPP_PRIMER_EX14_05_H
    
    

    book.cpp

    //
    // Created by wangheng on 2020/5/5.
    //
    
    #include "ex14_05.h"
    
    std::istream& operator>>(std::istream& in, Book& book) {
        in >> book.no >> book.name >> book.author >> book.pubDate;
        return in;
    }
    std::ostream& operator<<(std::ostream& os, const Book& book) {
        os << book.no << ' ' << book.name << ' ' << book.author << ' ' << book.pubDate;
        return os;
    }
    bool operator==(const Book& lhs, const Book& rhs) {
        return lhs.no == rhs.no;
    }
    bool operator!=(const Book& lhs, const  Book& rhs) {
        return !(lhs.no == rhs.no);
    }
    

    main.cpp

    //
    // Created by wangheng on 2020/5/5.
    //
    
    #include "ex14_05.h"
    
    int main() {
        Book book1(123, "Journey to the West", "Chengen Wu", "Ming dynasty");
        Book book2(123, "西游记", "吴承恩", "明朝");
        std::cout << book1 << ' ' << book2 << std::endl;
        std::cout << std::boolalpha << (book1 == book2) << std::endl;
        Book book3(std::cin);
        std::cout << (book2 == book3) << std::endl;
    
        return 0;
    }
    

    14.06|h|cpp

    为你的Sales_data类定义输出运算符。

    见练习14.2的代码

    14.07|h|cpp

    你在13.5节的练习(第470页)中曾经编写了一个String类,为它定义一个输出运算符。

    见练习13.44的代码

    14.08|h|cpp

    你在7.5.1节的练习7.40(第261页)中曾经选择并编写了一个类,为它定义一个输出运算符。

    见练习14.05的代码。

    14.09|h|cpp

    为你的Sales_data类定义输入运算符。

    见练习14.02的代码

    14.10

    对于Sales_data的输入运算符来说如果给定了下面的输入将发生什么情况?

    (a)0-201-99999-9 10 24.95
    (b)10 24.95 0-210-99999-9
    

    (a)格式正确,可以正常构造一个Sales_data对象

    (b)非法输入,因为程序试图将0-210-99999-9字符串转换为double类型,所以输入操作失败,但是输入运算符重载代码中处理了这一情况,会给读取失败的对象用默认构造函数初始化。

    14.11

    下面的 Sales_data 输入运算符存在错误吗?如果有,请指出来。对于这个输入运算符如果仍然给定上个练习的输入将会发生什么情况?

    istream& operator>>(istream& in, Sales_data& s)
    {
    	double price;
    	in >> s.bookNo >> s.units_sold >> price;
    	s.revence = s.units_sold * price;
    	return in;
    }
    
    

    存在错误,因为这样重载输入运算符没有对输入操作失败的情况进行处理。针对上一题,(a)格式正确,可以正常构造一个Sales_data对象,但是(b)由于输入格式错误,不能成功构造一个对象。

    14.12|h|cpp

    你在7.5.1节的练习中曾经选择并编写了一个类,为它定义一个输入运算符并确保该运算符可以处理输入错误。

    14.13|h|cpp

    你认为 Sales_data 类还应该支持哪些其他算术运算符?如果有的话,请给出它们的定义。

    Sales_data可以重载--=运算符。具体实现见练习14.02的代码。

    14.14

    你觉得为什么调用 operator+= 来定义operator+ 比其他方法更有效?

    因为用 operator+= 会避免使用一个临时对象,而使得更有效。

    14.15|h|cpp|test

    你在7.5.1节的练习7.40中曾经选择并编写了一个类,你认为它应该含有其他算术运算符吗?如果是,请实现它们;如果不是,解释原因。

    可以给Book类添加<>+-重载运算符。

    Book.h

    //
    // Created by wangheng on 2020/5/6.
    //
    
    #ifndef CPP_PRIMER_EX14_15_H
    #define CPP_PRIMER_EX14_15_H
    
    #include <iostream>
    #include <string>
    
    class Book {
        friend std::istream& operator>>(std::istream&, Book&);
        friend std::ostream& operator<<(std::ostream&, const Book&);
        friend bool operator==(const Book&, const Book&);
        friend bool operator!=(const Book&, const Book&);
        friend bool operator<(const Book&, const Book&);
        friend bool operator>(const Book&, const Book&);
        friend Book operator+(const Book&, const Book&);
        friend Book operator-(const Book&, const Book&);
    
    public:
        Book() = default;
        Book(unsigned no, std::string name, std::string author, std::string pubDate, unsigned number) :
                no(no), name(name), author(author), pubDate(pubDate), number(number) {}
        Book(std::istream& in) {in >> *this;}
        Book& operator+=(const Book&);
        Book& operator-=(const Book&);
    
    private:
        unsigned no;
        std::string name;
        std::string author;
        std::string pubDate;
        unsigned number = 0;
    };
    
    std::istream& operator>>(std::istream&, Book&);
    std::ostream& operator<<(std::ostream&, const Book&);
    bool operator==(const Book&, const Book&);
    bool operator!=(const Book&, const  Book&);
    bool operator<(const Book&, const Book&);
    bool operator>(const Book&, const Book&);
    Book operator+(const Book&, const Book&);
    Book operator-(const Book&, const Book&);
    
    #endif //CPP_PRIMER_EX14_15_H
    
    
    

    Book.cpp

    //
    // Created by wangheng on 2020/5/6.
    //
    
    #include "ex14_15.h"
    
    Book& Book::operator+=(const Book &rhs) {
        number += rhs.number;
        return *this;
    }
    
    Book& Book::operator-=(const Book &rhs) {
        number -= rhs.number;
        return *this;
    }
    
    std::istream& operator>>(std::istream& in, Book& book) {
        in >> book.no >> book.name >> book.author >> book.pubDate >> book.number;
        if (!in)
            book = Book();
        return in;
    }
    std::ostream& operator<<(std::ostream& os, const Book& book) {
        os << book.no << ' ' << book.name << ' ' << book.author << ' ' << book.pubDate << ' ' << book.number;
        return os;
    }
    bool operator==(const Book& lhs, const Book& rhs) {
        return lhs.no == rhs.no;
    }
    bool operator!=(const Book& lhs, const  Book& rhs) {
        return !(lhs.no == rhs.no);
    }
    
    bool operator<(const Book& lhs, const Book& rhs) {
        return lhs.no < rhs.no;
    }
    bool operator>(const Book&lhs, const Book& rhs) {
        return lhs.no > rhs.no;
    }
    Book operator+(const Book& lhs, const Book& rhs) {
        Book result = lhs;
        result += rhs;
        return result;
    }
    Book operator-(const Book& lhs, const Book& rhs) {
        Book result = lhs;
        result -= rhs;
        return result;
    }
    
    

    main.cpp

    //
    // Created by wangheng on 2020/5/6.
    //
    
    #include <iostream>
    #include "ex14_15.h"
    
    int main() {
        Book book1(123, "Journey to the West", "Chengen Wu", "Ming dynasty", 2);
        Book book2(123, "西游记", "吴承恩", "明朝", 3);
        std::cout << book1 << ' ' << book2 << std::endl;
        std::cout << std::boolalpha << (book1 == book2) << std::endl;
        Book book3(std::cin);
        std::cout << (book2 == book3) << std::endl;
        std::cout << (book1 + book2) << std::endl;
    
        return 0;
    }
    
    

    14.16

    为你的 StrBlob 类、StrBlobPtr 类、StrVec 类和 String 类分别定义相等运算符和不相等运算符。

    StrBlob|h|cpp

    StrBlobPtr|h|cpp

    StrVec|h|cpp

    String|h|cpp

    14.17

    你在7.5.1节中的练习7.40中曾经选择并编写了一个类,你认为它应该含有相等运算符吗?如果是,请实现它;如果不是,解释原因。

    应该有相等运算符,代码见练习14.05。h|cpp

    14.18

    为你的 StrBlob 类、StrBlobPtr 类、StrVec 类和 String 类分别定义关系运算符。

    StrBlob|h|cpp

    StrBlobPtr|h|cpp

    StrVec|h|cpp

    String|h|cpp

    14.19

    你在7.5.1节的练习7.40中曾经选择并编写了一个类,你认为它应该含有关系运算符吗?如果是,请实现它;如果不是,解释原因。

    应该有,代码见练习14.05。h|cpp

    14.20

    为你的 Sales_data 类定义加法和复合赋值运算符。

    参看练习14.02的代码。14.02

    14.21

    编写 Sales_data 类的+ 和+= 运算符,使得 + 执行实际的加法操作而 += 调用+。相比14.3节和14.4节对这两个运算符的定义,本题的定义有何缺点?试讨论之。

    缺点:使用了一个 Sales_data 的临时对象,但它并不是必须的。

    14.22h|cpp

    定义赋值运算符的一个新版本,使得我们能把一个表示 ISBN 的 string 赋给一个 Sales_data 对象。

    14.23|h|cpp

    为你的StrVec 类定义一个 initializer_list 赋值运算符。

    14.24

    你在7.5.1节的练习7.40中曾经选择并编写了一个类,你认为它应该含有拷贝赋值和移动赋值运算符吗?如果是,请实现它们。

    见练习14.15的代码。h|cpp|test

    14.25

    上题的这个类还需要定义其他赋值运算符吗?如果是,请实现它们;同时说明运算对象应该是什么类型并解释原因。

    是,如上题。

    14.26

    为你的 StrBlob 类、StrBlobPtr 类、StrVec 类和 String 类定义下标运算符。

    StrBlob|h|cpp

    StrBlobPtr|h|cpp

    StrVec|h|cpp

    String|h|cpp

    14.27|h|cpp

    为你的 StrBlobPtr 类添加递增和递减运算符。

    见练习12.19的代码。

    14.28|h|cpp

    为你的 StrBlobPtr 类添加加法和减法运算符,使其可以实现指针的算术运算。

    见练习12.19的代码。

    14.29

    为什么不定义const 版本的递增和递减运算符?

    因为递增和递减会改变对象本身,所以不能定义const版本的递增递减运算符。

    14.30

    为你的 StrBlobPtr 类和在12.1.6节练习12.22中定义的 ConstStrBlobPtr 的类分别添加解引用运算符和箭头运算符。注意:因为 ConstStrBlobPtr 的数据成员指向const vector,所以ConstStrBlobPtr 中的运算符必须返回常量引用。

    StrBlobPtr|h|cpp

    ConstStrBlobPtr|h|cpp

    14.31

    我们的 StrBlobPtr 类没有定义拷贝构造函数、赋值运算符以及析构函数,为什么?

    因为合成的默认版本足够满足要求。

    14.32

    定义一个类令其含有指向 StrBlobPtr 对象的指针,为这个类定义重载的箭头运算符。

    class StrBlobPtr;
    
    class StrBlobPtr_pointer
    {
    public:
        StrBlobPtr_pointer() = default;
        StrBlobPtr_pointer(StrBlobPtr* p) : pointer(p) { }
    
        StrBlobPtr& operator *();
        StrBlobPtr* operator->();
    
    private:
        StrBlobPtr* pointer = nullptr;
    };
    
    

    14.33

    一个重载的函数调用运算符应该接受几个运算对象?

    一个重载的函数调用运算符接受的运算对象应该和该运算符拥有的操作数一样多。

    14.34

    定义一个函数对象类,令其执行if-then-else 的操作:该类的调用运算符接受三个形参,它首先检查第一个形参,如果成功返回第二个形参值;如果不成功返回第三个形参的值。

    struct Test {
        int operator()(bool flag, int a, int b) {
            return flag ? a : b;
        }
    };
    
    

    14.35|cpp

    编写一个类似于 PrintString 的类,令其从 istream 中读取一行输入,然后返回一个表示我们所读内容的string。如果读取失败,返回空string。

    //
    // Created by wangheng on 2020/5/7.
    //
    
    #include <iostream>
    #include <string>
    
    class PrintString {
    public:
        PrintString(std::istream& is = std::cin) : is(is) {}
        std::string operator()() const {
            std::string str;
            std::getline(is, str);
            return is ? str : std::string();
        }
    
    private:
        std::istream& is;
    };
    
    int main() {
        PrintString printer;
        std::cout << printer() << std::endl;
    
        return 0;
    }
    
    

    14.36|cpp

    使用前一个练习定义的类读取标准输入,将每一行保存为 vector 的一个元素。

    //
    // Created by wangheng on 2020/5/7.
    //
    
    #include <iostream>
    #include <string>
    #include <vector>
    
    class PrintString {
    public:
        PrintString(std::istream& is = std::cin) : is(is) {}
        std::string operator()() const {
            std::string str;
            std::getline(is, str);
            return is ? str : std::string();
        }
    
    private:
        std::istream& is;
    };
    
    int main() {
        PrintString printer;
        std::vector<std::string> sv;
        for (std::string temp; !(temp = printer()).empty(); )
            sv.push_back(temp);
        for (const auto &str : sv)
            std::cout << str << ' ';
        std::cout << std::endl;
    
        return 0;
    }
    
    

    14.37|cpp

    编写一个类令其检查两个值是否相等。使用该对象及标准库算法编写程序,令其替换某个序列中具有给定值的所有实例。

    //
    // Created by wangheng on 2020/5/7.
    //
    
    #include <iostream>
    #include <algorithm>
    #include <vector>
    
    class IsEqual {
    public:
        IsEqual(int v) :value(v) {}
        bool operator()(int elem) {
            return value == elem;
        }
    
    private:
        int value;
    };
    
    int main() {
        std::vector<int> vec{3, 2, 1, 4, 3, 7};
        std::replace_if(vec.begin(), vec.end(), IsEqual(3), 5);
        for (int i : vec)
            std::cout << i << ' ';
        std::cout << std::endl;
    
        return 0;
    }
    
    

    14.38|cpp

    编写一个类令其检查某个给定的 string 对象的长度是否与一个阈值相等。使用该对象编写程序,统计并报告在输入的文件中长度为1的单词有多少个,长度为2的单词有多少个、......、长度为10的单词有多少个。

    //
    // Created by wangheng on 2020/5/7.
    //
    
    #include <iostream>
    #include <string>
    #include <fstream>
    #include <algorithm>
    #include <vector>
    #include <sstream>
    
    class GetLength {
    public:
        GetLength(std::size_t n) : sz(n) {}
        bool operator()(const std::string& s) {
            return s.size() == sz;
        }
    
    private:
        std::size_t sz;
    };
    
    int main() {
        std::ifstream infile("C:\Users\wh969\Desktop\code\CPP-Primer\data\ex14_38.txt", std::ios::in);
        std::vector<std::string> words;
        std::string line;
        while (std::getline(infile, line)) {
            std::istringstream line_words(line);
            std::string word;
            while (line_words >> word)
                words.push_back(word);
        }
    
        // 对words按长度从小到大排序
        std::stable_sort(words.begin(), words.end(),
                         [] (const std::string& s1, const std::string& s2) {return s1.size() < s2.size();});
    
        // 计算words中最长的string的长度
        std::size_t maxLength = (words.end() - 1)->size();
    
        for (std::size_t i = 1; i <= maxLength; ++i) {
            auto number = std::count_if(words.begin(), words.end(), GetLength(i));
            std::cout << "Length " << i << ": " << number << std::endl;
            auto first = std::find_if(words.begin(), words.end(), GetLength(i));
            for (auto iter = first; iter != first + number; ++iter)
                std::cout << *iter << ' ';
            std::cout << std::endl;
        }
    
        return 0;
    }
    
    

    14.39|cpp

    修改上一题的程序令其报告长度在1到9之间的单词有多少个、长度在10以上的单词有多少个。

    //
    // Created by wangheng on 2020/5/7.
    //
    
    #include <iostream>
    #include <string>
    #include <fstream>
    #include <algorithm>
    #include <vector>
    #include <sstream>
    
    class GetLength {
    public:
        GetLength(std::size_t n) : sz(n) {}
        bool operator()(const std::string& s) {
            return s.size() == sz;
        }
    
    private:
        std::size_t sz;
    };
    
    int main() {
        std::ifstream infile("C:\Users\wh969\Desktop\code\CPP-Primer\data\ex14_38.txt", std::ios::in);
        std::vector<std::string> words;
        std::string line;
        while (std::getline(infile, line)) {
            std::istringstream line_words(line);
            std::string word;
            while (line_words >> word)
                words.push_back(word);
        }
    
        // 对words按长度从小到大排序
        std::stable_sort(words.begin(), words.end(),
                         [] (const std::string& s1, const std::string& s2) {return s1.size() < s2.size();});
    
        std::size_t sz = 1;
        while (sz < 10) {
            auto number = std::count_if(words.begin(), words.end(), GetLength(sz));
            std::cout << "Length " << sz << ": " << number << std::endl;
            auto first = std::find_if(words.begin(), words.end(), GetLength(sz));
            for (auto iter = first; iter != first + number; ++iter)
                std::cout << *iter << ' ';
            std::cout << std::endl;
            ++sz;
        }
        auto first = std::find_if(words.begin(), words.end(),
                [sz](const std::string& s) {return s.size() >= sz;});
        std::cout << "Length >= 10: " << words.end() - first << std::endl;
        for (auto iter = first; iter != words.end(); ++iter)
            std::cout << *iter << ' ';
        std::cout << std::endl;
    
        return 0;
    }
    
    

    14.40|cpp

    重新编写10.3.2节的biggies 函数,使用函数对象替换其中的 lambda 表达式。

    //
    // Created by wangheng on 2020/5/7.
    //
    
    #include <iostream>
    #include <string>
    #include <algorithm>
    #include <vector>
    
    class ShorterString {
    public:
        bool operator()(const std::string& s1, const std::string& s2) const {
            return s1.size() < s2.size();
        }
    };
    
    class BiggerEqual {
    public:
        BiggerEqual(std::size_t n) : sz(n) {}
        bool operator()(const std::string& s) {
            return s.size() >= sz;
        }
    
    private:
        std::size_t sz;
    };
    
    class Printer {
    public:
        Printer(std::ostream& os = std::cout, std::string str = " ") :
            os(os), str(str) {}
        void operator()(const std::string& s) {
            os << s << str;
        }
    
    private:
        std::ostream& os;
        std::string str;
    };
    
    std::string make_plural(std::size_t ctr, const std::string &word, const std::string& ending) {
        return (ctr > 1) ? word + ending : word;
    }
    
    // 将wors按字典顺序排序,删除重复单词
    void elimDups(std::vector<std::string>& words) {
        std::sort(words.begin(), words.end());
        auto end_unique = std::unique(words.begin(), words.end());
        words.erase(end_unique, words.end());
    }
    
    void biggies(std::vector<std::string>& words, std::vector<std::string>::size_type sz) {
        elimDups(words);
        std::stable_sort(words.begin(), words.end(), ShorterString());
        auto wc = std::find_if(words.begin(), words.end(), BiggerEqual(sz));
        auto count = words.end() - wc;
        std::cout << count << " " << make_plural(count, "word", "s")
            << " of length " << sz << " or longer" << std::endl;
        std::for_each(wc, words.end(), Printer());
        std::cout << std::endl;
    }
    
    int main() {
        std::vector<std::string> words = {"an", "the", "good", "football", "bike", "Chinese"};
        biggies(words, 4);
    
        return 0;
    }
    
    

    14.41

    你认为 C++ 11 标准为什么要增加 lambda?对于你自己来说,什么情况下会使用 lambda,什么情况下会使用类?

    使用lambda非常方便,当需要使用一个函数且这个函数非常简单和不常用时,使用lambda是比较简单的选择。

    14.42

    使用标准库函数对象及适配器定义一条表达式,令其

    (a) 统计大于1024的值有多少个。 
    (b) 找到第一个不等于pooh的字符串。
    (c)将所有的值乘以2。
    
    

    统计大于1024的值的个数:

    #include <iostream>
    #include <functional>
    #include <vector>
    #include <algorithm>
    
    int main() {
        std::vector<int> vec = {1,2,3,1025,2343,43554};
        auto count = std::count_if(vec.begin(), vec.end(),
                std::bind(std::greater<int>(), std::placeholders::_1, 1024));
        std::cout << count << std::endl;
    
        return 0;
    }
    
    

    找到第一个不等于pooh的字符串:

    #include <iostream>
    #include <functional>
    #include <vector>
    #include <algorithm>
    #include <string>
    
    int main() {
        std::vector<std::string> vec{"pooh", "pooh", "pooh", "good", "pooh"};
        auto first = std::find_if(vec.begin(), vec.end(),
                std::bind(std::not_equal_to<std::string>(), std::placeholders::_1, "pooh"));
        std::cout << *first << std::endl;
    
        return 0;
    }
    
    

    将所有的值乘2:

    #include <iostream>
    #include <functional>
    #include <vector>
    #include <algorithm>
    
    int main() {
        std::vector<int> vec{1,2,3,4,5,6};
        std::transform(vec.begin(), vec.end(), vec.begin(),
                std::bind(std::multiplies<int>(), std::placeholders::_1, 2));
        for (auto iter = vec.begin(); iter != vec.end(); ++iter)
            std::cout << *iter << ' ';
        std::cout << std::endl;
    
        return 0;
    }
    
    

    14.43|cpp

    使用标准库函数对象判断一个给定的int值是否能被 int 容器中的所有元素整除。

    //
    // Created by wangheng on 2020/5/8.
    //
    
    #include <iostream>
    #include <algorithm>
    #include <functional>
    #include <vector>
    
    int main() {
        bool flag = true;
        std::vector<int> vec{2,6,4,8};
        // 判断2是否能被容器内的所有元素整除
        auto count = std::count_if(vec.begin(), vec.end(),
                std::bind(std::equal_to<int>(), std::bind(std::modulus<int>(), std::placeholders::_1, 2), 0));
        if (count != vec.size())
            flag = false;
        std::cout << std::boolalpha << flag << std::endl;
    
        return 0;
    }
    
    

    14.44|cpp

    编写一个简单的桌面计算器使其能处理二元运算。

    //
    // Created by wangheng on 2020/5/8.
    //
    
    #include <iostream>
    #include <map>
    #include <functional>
    #include <string>
    
    int add(int i, int j) { return i + j; }
    auto mod = [](int i, int j) { return i % j; };
    struct Div {int operator()(int i, int j) { return i / j; }};
    
    auto binops = std::map<std::string, std::function<int(int, int)>> {
            {"+", add},                         // function pointer
            {"-", std::minus<int>()},       //library functor
            {"/", Div()},                   // user-defined functor
            {"*", [](int i, int j) { return i * j; }},   //unnamed lambda
            {"%", mod}                          // named lambda
    };
    
    int main() {
        while (std::cout << "Please enter as: num operator num: 
    ", true) {
            int lhs, rhs;
            std::string op;
            std::cin >> lhs >> op >> rhs;
            std::cout << binops[op](lhs, rhs) << std::endl;
        }
        return 0;
    }
    
    

    14.45|h|cpp

    编写类型转换运算符将一个 Sales_data 对象分别转换成 stringdouble,你认为这些运算符的返回值应该是什么?

    14.46

    你认为应该为 Sales_data 类定义上面两种类型转换运算符吗?应该把它们声明成 explicit 的吗?为什么?

    上面的两种类型转换有歧义,应该声明成explicit的。

    14.47

    说明下面这两个类型转换运算符的区别。

    struct Integral {
    	operator const int();
    	operator int() const;
    }
    
    

    第一个无意义,将被编译器忽略,第二个合法,将Integral类转换为int

    14.48

    你在7.5.1节的练习7.40中曾经选择并编写了一个类,你认为它应该含有向 bool 的类型转换运算符吗?如果是,解释原因并说明该运算符是否应该是 explicit的;如果不是,也请解释原因。

    Date类应该有向bool的类型转换运算符,且应该声明成explicit的,避免某些情况隐式转换成bool类型造成莫名的错误。

    14.49

    为上一题提到的类定义一个转换目标是 bool 的类型转换运算符,先不用在意这么做是否应该。

    explicit operator bool() const { return year < 4000 ? true : false; }
    
    

    14.50

    在初始化 ex1ex2的过程中,可能用到哪些类类型的转换序列呢?说明初始化是否正确并解释原因。

    struct LongDouble {
    	LongDouble(double = 0.0);
    	operator double();
    	operator float();
    };
    LongDouble ldObj;
    int ex1 = ldObj;
    float ex2 = ldObj;
    
    

    ex1转换不合法, 类型转换时出现二义性,ex2转换合法,调用operator float()

    14.51

    在调用 calc 的过程中,可能用到哪些类型转换序列呢?说明最佳可行函数是如何被选出来的。

    void calc(int);
    void calc(LongDouble);
    double dval;
    calc(dval);  //哪个calc?
    
    

    最佳可行函数时void calc(int)

    转换的优先级如下:

    1. 精确匹配
    2. const转换
    3. 类型转换
    4. 算术转换
    5. 类类型转换

    calc(dval)执行时,将dval使用类型转换成int,调用void calc(int)

    14.52

    在下面的加法表达式中分别选用了哪个operator+?列出候选函数、可行函数及为每个可行函数的实参执行的类型转换:

    struct Longdouble {
    	//用于演示的成员operator+;在通常情况下是个非成员
    	LongDouble operator+(const SmallInt&);
    	//其他成员与14.9.2节一致
    };
    LongDouble operator+(LongDouble&, double);
    SmallInt si;
    LongDouble ld;
    ld = si + ld;
    ld = ld + si;
    
    

    ls = si + ld不合法,两个opearator+函数的形参第一个都应该是LongDouble

    ld = ld + si合法,两个候选函数都匹配,但是第一个是精确匹配,第二个需要将si先转换为int,再转换为double然后才能匹配。

    14.53

    假设我们已经定义了如第522页所示的SmallInt,判断下面的加法表达式是否合法。如果合法,使用了哪个加法运算符?如果不合法,应该怎样修改代码才能使其合法?

    SmallInt si;
    double d = si + 3.14;
    
    

    不合法,会出现二义性。将si转换为int再转换为double然后进行相加,还是将3.14转换为int再通过构造函数转换为SmallInt然后进行相加。

    可以改为:

    1. double d = si + SmallInt(3.14);
  • 相关阅读:
    Ubuntu mongodb 安装和配置
    最基本的SQL语法/语句
    Sphinx学习之sphinx的安装篇
    六关节机器人的雅可比矩阵及微分运算
    六关节机器人的逆运动学计算
    六关节机器人的正运动学计算
    六关节机器人末端的微分运动
    Python3 升级pip
    一般多项式曲线的最小二乘回归(Linear Regression)
    关于卡尔曼滤波(Kalman Filter)的很好讲解
  • 原文地址:https://www.cnblogs.com/hengwangg/p/13289558.html
Copyright © 2011-2022 走看看