c++primer 14.1-14.15

2019-06-12  本文已影响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;
}
上一篇下一篇

猜你喜欢

热点阅读