美文网首页
c++primer 14.1-14.15

c++primer 14.1-14.15

作者: 青吟乐 | 来源:发表于2019-06-12 23:13 被阅读0次

    14.1
    当重载的运算符与内置运算符的参数,运行方式,中间过程不一样的时候两者有区别,但是在运算的优先级上,运算规则上面就一样。
    14.2

    #ifndef SALES_DATA_H_INCLUDED
    #define SALES_DATA_H_INCLUDED
    
    #include <string>
    #include <iostream>
    
    class Sales_data
    {
        //重载>>运算符
        friend std::istream& operator>>(std::istream&, Sales_data&);
        //重载<<运算符
        friend std::ostream& operator<<(std::ostream&, const Sales_data&);
        //重载+运算符
        friend Sales_data 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) {}
        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;
    };
    
    inline double Sales_data::avg_price() const
    {
        return units_sold ? revenue / units_sold : 0;
    }
    Sales_data::Sales_data(std::istream &is) : Sales_data()
    {
        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, const 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;//拷贝lhs到sum
        sum += rhs;//进行对象的加法运算
        return sum;//返回对象的合成移动拷贝(右值)
    }
    
    #endif // SALES_DATA_H_INCLUDED
    
    

    14.3
    (a) 用的是判定运算符 不是string,也不是vector的==
    (b)string的==
    (c)vector的==
    (d)我看不懂啥情况,前面多了一个双引号,要是没有那个双引号就是string的==
    14.4
    判断方法:默认是否可以直接对对象进行操作
    (a)不需要重新定义即可使用,所以不需要是类成员
    (b)%=改变了对象属性,所以要重新定义
    (c)++也对对象的属性进行了改变,所以要自己定义
    (d)是
    (e)标准输出,不用是
    (f)同e
    (g)标准别断,不用是
    (h)是
    14.5
    先来看看book类和其重载的运算符,重载了<<,>>,==,!=四个

    #ifndef BOOK_H_INCLUDED
    #define BOOK_H_INCLUDED
    
    
    #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 &in, Book &book)
    {
        //规范输入构造
        in >> book.no_ >> book.name_ >> book.author_ >> book.pubdate_;
        return in;
    }
    //重载<<
    std::ostream& operator<<(std::ostream &out, const Book &book)
    {
        //规范输出
        out << book.no_ << " " << book.name_ << " " << book.author_ << " " << book.pubdate_;
        return out;
    }
    //重载==
    bool operator==(const Book &lhs, const Book &rhs)
    {
        //判断no_
        return lhs.no_ == rhs.no_;
    }
    //重载!=
    bool operator!=(const Book &lhs, const Book &rhs)
    {
        //判断no_
        return !(lhs == rhs);
    }
    
    #endif // BOOK_H_INCLUDED
    
    

    再看看对四个重载运算符的测试

    #include <iostream>
    #include"Sales_data.h"
    #include<vector>
    #include"Book.h"
    
    int main()
    {   Book book1(12, "xxx", "leifeng", "1995");
        Book book2(12, "xxx", "leifeng", "1995");
        Book book3(11, "xxx", "leifeng", "1995");
    
        if (book1 == book2)
            std::cout << book1 << std::endl;
        if (book2 == book3){
            std::cout << book2 << std::endl;
        }else{
            std::cout << book1 << std::endl;
        }
        if(book2 != book3){
            std::cout << book1 << std::endl;
        }
        Book book4;
        std::cin>>book4;
        std::cout << book4 << std::endl;
        return 0;
    }
    

    使用正常
    14.6
    见14.2中对<<的重载,注意要对重载<<运算符声明成友元函数,要不然左侧对象
    14.7

    #ifndef STRING_H_INCLUDED
    #define STRING_H_INCLUDED
    
    #include <string>
    #include <algorithm>
    #include <memory>
    #include <vector>
    #include<iostream>
    class String{
        //重载<<
        friend std::ostream& operator<<(std::ostream&, const String&);
    public:
        String():String(""){}                                        //默认构造函数
        String(const char *s){
            auto s1 = const_cast<char*> (s);             //const_cast的作用就是解const
            for(;*s1;s1++){range_initializer(s, s1);}                              //计算字符长度
                                      //申请内存
        }
        String(const String&);
        String & operator=(const String& );
        ~String(){
            free();
        }
        void free(){
            if(elements){//若elements不为空
                std::for_each(elements,first_free,[this](char &c){alloc.destroy(&c);});
                alloc.deallocate(elements,first_free-elements);
            }
        }
    
    
        //移动构造函数
        String(String &&s) noexcept;
        //移动构造运算符
        String & operator=(String &&rhs) noexcept;
        void range_initializer(const char*, const char*);
        const char *c_str() const { return elements; }
    private:
        std::allocator<char> alloc;                      //用于申请内存
        char *elements;                                  //首指针
        char *first_free;                                //尾后指针
    
        std::pair<char*,char*> alloc_n_copy(const char *a,const char *b){
            auto first_address = alloc.allocate(b-a);                        //返回申请内存的首指针
            auto last_f_address = std::uninitialized_copy(a,b,first_address);//返回构造后的尾后指针
            return {first_address,last_f_address};                           //以pair的形式返回
        }
    };
    
    void String::range_initializer(const char *first, const char *last)
    {
        auto newstr = alloc_n_copy(first, last);
        elements = newstr.first;
        first_free = newstr.second;
    }
    
    
    
    String::String(const String&s){
        std::cout<<"拷贝构造函数"<<std::endl;
        auto newStr = alloc_n_copy(s.elements,s.first_free);
        elements = newStr.first;
        first_free = newStr.second;
    }
    
    String& String::operator=(const String&a){
        std::cout<<"拷贝赋值运算符"<<std::endl;
        auto newc = alloc_n_copy(a.elements,a.first_free);
        free();
        elements = newc.first;
        first_free = newc.second;
        return *this;
    }
    //移动构造函数
    String::String(String &&s) noexcept{
        std::cout<<"移动构造函数"<<std::endl;
        elements = s.elements;
        first_free = s.first_free;
        s.elements = s.first_free = nullptr;
    
    }
    //移动赋值运算符
    String &String::operator=(String &&rhs) noexcept{
        std::cout<<"移动赋值运算符"<<std::endl;
        if(this!=&rhs){
            free();
            elements = rhs.elements;
            first_free = rhs.first_free;
            rhs.elements = rhs.first_free = nullptr;
        }
        return *this;
    }
    std::ostream& operator<<(std::ostream &os, const String &s)
    {
        char *c = const_cast<char*>(s.c_str());
        while (*c)
            os << *c++;
        return os;
    }
    
    #endif // STRING_H_INCLUDED
    
    

    测试一下

        String  s("xxxdsxx");
        std::cout<<s<<std::endl;
    

    可以
    14.8
    参考上面的14.5
    14.9
    注意使用友元函数

        friend std::istream& operator>>(std::istream&, Sales_data&);
    
    
    //实现>>运算符
    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;//最后返回输入流
    }
    

    14.10
    a 输入没有问题
    b 输入产生问题 24.95被转换成int类型 0-210-99999-9被修改成dounle类型(ps:用的codeblocks成功计算什么鬼,讲道理不应该是0吗)
    14.11
    输入数据有误,但是并不检查,什么都不会发生,最后就算结果0
    14.12

    //重载>>
    std::istream& operator>>(std::istream &in, Book &book)
    {
        //规范输入构造
        in >> book.no_ >> book.name_ >> book.author_ >> book.pubdate_;
        if(!in){
            //输入出现问题就自己处理一下参数
            std::cout<<"输入有误,使用默认值"<<std::endl;
            book.no_  =  0;
            book.author_ = "null";
            book.pubdate_ = "null";
    
        }
        return in;
    }
    

    14.13

    14.14
    operator+=返回对本对象进行修改,返回当前对象的指针但是operator=返回的一个副本,尽管有可能使用了移动构造函数,但是还是不如返回当前对象的指针高效
    14.15
    book类和方法

    #ifndef BOOK_H_INCLUDED
    #define BOOK_H_INCLUDED
    
    
    #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&);
    
    
    public:
        //使用默认的构造函数
        Book() = default;
        //5参数构造
        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 &rhs);
    private:
        unsigned no_;
        std::string name_;
        std::string author_;
        std::string pubdate_;
        unsigned number_;
    };
    //重载>>
    std::istream& operator>>(std::istream &in, Book &book)
    {
        //规范输入构造
        in >> book.no_ >> book.name_ >> book.author_ >> book.pubdate_;
        if(!in){
            //输入出现问题就自己处理一下参数
            std::cout<<"输入有误,使用默认值"<<std::endl;
            book.no_  =  0;
            book.author_ = "null";
            book.pubdate_ = "null";
    
        }
        return in;
    }
    //重载<<
    std::ostream& operator<<(std::ostream &out, const Book &book)
    {
        //规范输出
        out << book.no_ << " " << book.name_ << " " << book.author_ << " " << book.pubdate_;
        return out;
    }
    //重载==
    bool operator==(const Book &lhs, const Book &rhs)
    {
        //判断no_
        return lhs.no_ == rhs.no_;
    }
    //重载!=
    bool operator!=(const Book &lhs, const Book &rhs)
    {
        //判断no_
        return !(lhs == rhs);
    }
    
    //重载<
    bool operator<(const Book &lhs, const Book &rhs)
    {
        return lhs.no_ < rhs.no_;
    }
    //重载>,使用了<
    bool operator>(const Book &lhs, const Book &rhs)
    {
        //翻过来用<
        return rhs < lhs;
    }
    //重载+=
    Book& Book::operator+=(const Book &rhs)
    {
        if (rhs == *this)
            this->number_ += rhs.number_;
    
        return *this;
    }
    //重载+
    Book operator+(const Book &lhs, const Book &rhs)
    {
        Book book = lhs;
        book += rhs;
        return book;
    }
    #endif // BOOK_H_INCLUDED
    
    

    测试数据

    #include <iostream>
    #include"Sales_data.h"
    #include<vector>
    #include"Book.h"
    #include"String.h"
    
    int main()
    {
        Book book1(12, "xxx", "leifeng", "1995",5);
        std::cout << book1 << std::endl;
        Book book2(12, "xxx", "leifeng", "1995",3);
        Book book3(11, "xxx", "leifeng", "1995",4);
        book1+=book2;
        std::cout << book1 << std::endl;
        bool b = book1<book2;
        std::cout<<b<<std::endl;
        bool a = book1>book3;
        std::cout<<a<<std::endl;
    
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:c++primer 14.1-14.15

          本文链接:https://www.haomeiwen.com/subject/nsyrfctx.html