IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++ Primer 中文第 5 版练习答案 第 14 章 操作重载与类型转换(1~53) -> 正文阅读

[C++知识库]C++ Primer 中文第 5 版练习答案 第 14 章 操作重载与类型转换(1~53)

C++ Primer 中文版(第 5 版)练习解答合集

自己写的解答,如有错误之处,烦请在评论区指正!


1

相同点:

  • 参数数量和内置运算符相同
  • 优先级、结合性和内置运算符相同

不同点:

  • 重载的运算符要么是类的成员,要么至少含有一个类类型的参数
  • 重载的 &&|| 不保证短路求值

2

#pragma once

#include <iostream>
using std::istream;
using std::ostream;
using std::endl;
#include <string>
using std::string;

class Sales_data {
	friend istream& operator>>(istream& is, Sales_data& item);
	friend ostream& operator<<(ostream& os, const Sales_data& item);

public:
	Sales_data() = default;
	Sales_data(const string& s) : bookNo(s) { }
	Sales_data(const string& s, unsigned n, double p) :
		bookNo(s), units_sold(n), revenue(p*n) { }
	Sales_data(istream& is) {
		double price = 0;
		is >> bookNo >> units_sold >> price;
		revenue = price * units_sold;
	}

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

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

	std::string isbn() const {
		return bookNo;
	}

	double avg_price() const {
		return revenue / static_cast<double>(units_sold);
	}

private:
	string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};

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

ostream& operator<<(ostream& os, const Sales_data& item) {
	os << "isbn: " << item.isbn() << endl
		<< "units sold: " << item.units_sold << endl
		<< "revenue: " << item.revenue << endl
		<< "average price: " << item.avg_price() << endl;
	return os;
}

3

a. 重载的 string 的 ==

b. 重载的 string 的 ==

c. 重载的 vector 的 ==

d. 重载的 string 的 ==

4

% 出于对称性考虑一般不作为成员

%= 复合赋值一般是成员

++ 改变对象状态,一般是成员

-> 必须是成员

<< 如果作为输出运算符一般不是,因为按照习惯左侧参数通常是一个输出流

&& 因为重载后不保证短路求值,不建议重载。如果重载了,出于对称性考虑一般不作为成员

== 出于对称性考虑一般不作为成员

() 必须是成员

5

Book:重载输入输出、相等比较

Date:重载输入输出、相等比较、大小比较、递增递减,可能会有和 int 的加减法

Employee:重载输入输出、相等比较

6

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

7

ostream& operator<<(ostream& os, const String& s) {
	for (char* p = s.begin(); p != s.end(); ++p)
		putchar(*p);
	return os;
}

8

9

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

10

a. 正常输入所有数据

b. 能正常运行,但是会读取错误的数据,并且输入流中会有残留的数据干扰下一次读取

#include <iostream>
using std::cin;
using std::cout;
using std::endl;
#include <string>
using std::string;
#include "Sales_data.h"

// 输入:
// 10 24.95 0-210-99999-9
// 10 24.95 0-210-99999-9

int main()
{
    Sales_data s1;
    cin >> s1;
    cout << s1 << endl;
    cin >> s1;
    cout << s1 << endl;
}

运行结果:

10 24.95 0-210-99999-9
isbn: 10
units sold: 24
revenue: 22.8
average price: 0.95

10 24.95 0-210-99999-9
isbn: 0-210-99999-9
units sold: 10
revenue: 249.5
average price: 24.95

11

没有判断输入流出错的情况。会读入错误的数据。

12

13

不需要其他算术运算符了

14

因为一般在实现 + 的时候需要返回一个局部变量的值,而先令这个局部变量等于 lhs 的值,再 += rhs 的值,代码实现很方便。

15

16

StrBlob:(部分成员的实现略)

class StrBlob {
	friend class StrBlobPtr;

public:
	typedef vector<string>::size_type size_type;

	StrBlob();
	StrBlob(initializer_list<string> il);

	size_type size() const { return data->size(); }
	bool empty() const { return data->empty(); }
	void push_back(const string& t) {
		data->push_back(t);
	}
	void push_back(string&& t) {
		data->push_back(std::move(t));
	}
	void pop_back();
	string& front() &;
	const string& front() const&;
	string& back() &;
	const string& back() const&;
	StrBlobPtr begin();
	StrBlobPtr end();

	bool operator==(const StrBlob& rhs) {
		return data == rhs.data;
	}
	bool operator!=(const StrBlob& rhs) {
		return !(data == rhs.data);
	}

private:
	shared_ptr<vector<string>> data;

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

StrBlobPtr:(部分成员的实现略)

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

	bool equ(const StrBlobPtr& rhs) {
		auto spl = this->wptr.lock();
		auto spr = rhs.wptr.lock();
		if (spl != spr)
			return false;
		else
			return this->curr == rhs.curr;
	}
	bool neq(const StrBlobPtr& rhs) {
		return !(this->equ(rhs));
	}

	bool operator==(const StrBlobPtr& rhs) {
		shared_ptr<vector<string>> spl = wptr.lock(), spr = rhs.wptr.lock();
		if (spl == spr) {
			if (!spl)
				return true;
			else
				return curr == rhs.curr;
		} else {
			return false;
		}
	}

	bool operator!=(const StrBlobPtr& rhs) {
		return !(*this == rhs);
	}

private:
	shared_ptr<vector<string>> check(size_t i, const string& msg) const;

	weak_ptr<vector<string>> wptr;
	size_t curr;
};

StrVec:

#pragma once
#include <iostream>
using std::cout;
using std::endl;
#include <memory>
using std::allocator;
#include <string>
using std::string;
#include <utility>
using std::pair;
#include <algorithm>
#include <initializer_list>
using std::initializer_list;

class StrVec {
public:
	StrVec() :
		elements(nullptr), first_free(nullptr), cap(nullptr) { }
	StrVec(const initializer_list<string>& list) {
		auto newdata = alloc_n_copy(list.begin(), list.end());
		elements = newdata.first;
		first_free = cap = newdata.second;
	}
	StrVec(const StrVec& s) {
		auto newdata = alloc_n_copy(s.begin(), s.end());
		elements = newdata.first;
		first_free = cap = newdata.second;
	}
	StrVec(StrVec&& s) noexcept :
		elements(s.elements), first_free(s.first_free), cap(s.cap) {
		s.elements = s.first_free = s.cap = nullptr;
	}
	StrVec& operator=(const StrVec& rhs) {
		auto data = alloc_n_copy(rhs.begin(), rhs.end());
		free();
		elements = data.first;
		first_free = cap = data.second;
		return *this;
	}
	StrVec& operator=(StrVec&& rhs) noexcept {
		if (this != &rhs) {
			free();
			elements = rhs.elements;
			first_free = rhs.first_free;
			cap = rhs.cap;
			rhs.elements = rhs.first_free = rhs.cap = nullptr;
		}
		return *this;
	}
	
	bool operator==(const StrVec& rhs) const {
		if (size() == rhs.size()) {
			for (auto itl = begin(), itr = rhs.begin();
				itl != end(); ++itl, ++itr) {
				if (*itl != *itr)
					return false;
			}
			return true;
		} else {
			return false;
		}
	}

	bool operator!=(const StrVec& rhs) const {
		return !(*this == rhs);
	}

	~StrVec() {
		free();
	}
	void reserve(const size_t newcapacity) {
		auto newdata = alloc.allocate(newcapacity);
		auto dest = newdata;
		auto elem = elements;
		for (size_t i = 0; i != size(); ++i)
			alloc.construct(dest++, std::move(*elem++));
		free();
		elements = newdata;
		first_free = dest;
		cap = elements + newcapacity;
	}
	void resize(const size_t newSize) {
		if (newSize <= size()) {
			first_free = elements + newSize;
		} else {
			reserve(newSize);
			while (first_free != elements + newSize) {
				alloc.construct(first_free++, "");
			}
		}
	}
	void push_back(const string& s) {
		chk_n_alloc();
		alloc.construct(first_free++, s);
	}
	void push_back(string&& s) {
		chk_n_alloc();
		alloc.construct(first_free++, std::move(s));
	}
	size_t size() const {
		return  first_free - elements;
	}
	size_t capacity() const {
		return cap - elements;
	}
	string* begin() const {
		return elements;
	}
	string* end() const {
		return first_free;
	}
	string& operator[] (const int index) {
		return *(elements + index);
	}
	const string& operator[] (const int index) const {
		return *(elements + index);
	}
	void display() const {
		for (auto it = begin(); it != end(); ++it)
			cout << *it << endl;
	}

private:
	static allocator<string> alloc;
	void chk_n_alloc() {
		if (size() == capacity())
			reallocate();
	}
	pair<string*, string*> alloc_n_copy(const string* b, const string* e) {
		auto data = alloc.allocate(e - b);
		return { data, uninitialized_copy(b, e, data) };
	}
	void free() {
		//if (elements) {
		//	for (auto p = first_free; p != elements; /*null*/)
		//		alloc.destroy(--p);
		//	alloc.deallocate(elements, cap - elements);
		//}
		for_each(elements, first_free, [this](string& s) {
			alloc.destroy(&s);
		});
		alloc.deallocate(elements, cap - elements);
	}
	void reallocate() {
		auto newcapacity = size() ? 2 * size() : 1;
		auto newdata = alloc.allocate(newcapacity);
		auto dest = newdata;
		auto elem = elements;
		for (size_t i = 0; i != size(); ++i)
			alloc.construct(dest++, std::move(*elem++));
		free();
		elements = newdata;
		first_free = dest;
		cap = elements + newcapacity;
	}

	string* elements;
	string* first_free;
	string* cap;
};

allocator<string> StrVec::alloc;

String:

#pragma once

#include <iostream>
using std::ostream;
using std::cout;
using std::endl;
#include <memory>
using std::allocator;
using std::uninitialized_copy;
#include <utility>
using std::pair;
#include <algorithm>
#include <initializer_list>
using std::initializer_list;
#include <cstring>

class String {
	friend ostream& operator<<(ostream& os, const String& s);

public:
	String() :
		elements(nullptr), first_free(nullptr), cap(nullptr) { }
	String(const char* str) {
		if (!str || !*str)
			return;
		const char* p = str;
		first_free = elements = alloc.allocate(strlen(str));
		while (*p) {
			alloc.construct(first_free++, *p++);
		}
		cap = first_free;
	}
	String(const String& str) {
		cout << "Copy construct" << endl;
		auto newdata = alloc_n_copy(str.elements, str.first_free);
		elements = newdata.first;
		first_free = cap = newdata.second;
	}
	String(String&& str) noexcept :
		elements(str.elements), first_free(str.first_free), cap(str.cap) {
		cout << "Move construct" << endl;
		str.elements = str.first_free = str.cap = nullptr;
	}
	String& operator=(const String& rhs) {
		cout << "Copy assignment" << endl;
		auto data = alloc_n_copy(rhs.elements, rhs.first_free);
		free();
		elements = data.first;
		first_free = cap = data.second;
		return *this;
	}
	String& operator=(String&& rhs) {
		cout << "Move assignment" << endl;
		if (this != &rhs) {
			free();
			elements = rhs.elements;
			first_free = rhs.first_free;
			cap = rhs.cap;
			rhs.elements = rhs.first_free = rhs.cap = nullptr;
		}
		return *this;
	}
	~String() {
		free();
	}

	void reserve(const size_t newcapacity) {
		auto newdata = alloc.allocate(newcapacity);
		auto dest = newdata;
		auto elem = elements;
		for (size_t i = 0; i != size(); ++i)
			alloc.construct(dest++, std::move(*elem++));
		free();
		elements = newdata;
		first_free = dest;
		cap = elements + newcapacity;
	}
	void resize(const size_t newSize) {
		if (newSize <= size()) {
			first_free = elements + newSize;
		} else {
			reserve(newSize);
			while (first_free != elements + newSize) {
				alloc.construct(first_free++, '\0');
			}
		}
	}
	void push_back(const char ch) {
		chk_n_alloc();
		alloc.construct(first_free++, ch);
	}

	size_t size() const {
		return first_free - elements;
	}
	size_t capacity() const {
		return cap - elements;
	}
	char* begin() const {
		return elements;
	}
	char* end() const {
		return first_free;
	}

	bool operator==(const String& rhs) const {
		if (size() == rhs.size()) {
			for (auto itl = begin(), itr = rhs.begin();
				itl != end(); ++itl, ++itr) {
				if (*itl != *itr)
					return false;
			}
			return true;
		} else {
			return false;
		}
	}

	bool operator!=(const String& rhs) const {
		return !(*this == rhs);
	}


private:
	static allocator<char> alloc;
	void chk_n_alloc() {
		if (size() == capacity())
			reallocate();
	}
	pair<char*, char*> alloc_n_copy(const char* b, const char* e) {
		auto data = alloc.allocate(e - b);
		return { data, uninitialized_copy(b, e, data) };
	}
	void free() {
		std::for_each(elements, first_free, [this](char& c) {
			alloc.destroy(&c);
		});
		alloc.deallocate(elements, cap - elements);
	}
	void reallocate() {
		auto newcapacity = size() ? 2 * size() : 1;
		auto newdata = alloc.allocate(newcapacity);
		auto dest = newdata;
		auto elem = elements;
		for (size_t i = 0; i != size(); ++i)
			alloc.construct(dest++, std::move(*elem++));
		free();
		elements = newdata;
		first_free = dest;
		cap = elements + newcapacity;
	}

	char* elements;
	char* first_free;
	char* cap;
};

allocator<char> String::alloc;

ostream& operator<<(ostream& os, const String& s) {
	for (char* p = s.begin(); p != s.end(); ++p)
		putchar(*p);
	return os;
}

17

18

StrBlob:

bool operator<(const StrBlob& rhs) const {
    return *data < *rhs.data;
}
bool operator>(const StrBlob& rhs) const {
    return *data > *rhs.data;
}
bool operator<=(const StrBlob& rhs) const {
    return *data <= * rhs.data;
}
bool operator>=(const StrBlob& rhs) const {
    return *data >= *rhs.data;
}

StrBlobPtr:

bool operator<(const StrBlobPtr& rhs) const {
    shared_ptr<vector<string>> spl = wptr.lock(), spr = rhs.wptr.lock();
    if (spl == spr) {
        if (!spl)
            return false;
        else
            return curr < rhs.curr;
    } else {
        return false;
    }
}
bool operator>(const StrBlobPtr& rhs) const {
    if (*this == rhs || *this < rhs)
        return false;
    else
        return true;
}
bool operator<=(const StrBlobPtr& rhs) const {
    return *this < rhs || *this == rhs;
}
bool operator>=(const StrBlobPtr& rhs) const {
    return *this > rhs || *this == rhs;
}

StrVec:

bool operator<(const StrVec& rhs) const {
    auto itl = begin(), itr = rhs.begin();
    for (/*null*/; itl != end() && itr != rhs.end(); ++itl, ++itr) {
        if (*itl > * itr)
            return false;
        else if (*itl < *itr)
            return true;
    }
    if (itl == end() && itr != rhs.end())
        return true;
    else
        return false;
}
bool operator>(const StrVec& rhs) const {
    return !(*this == rhs || *this < rhs);
}
bool operator>=(const StrVec& rhs) const {
    return *this > rhs || *this == rhs;
}
bool operator<=(const StrVec& rhs) const {
    return *this < rhs || *this == rhs;
}

String:

bool operator<(const String& rhs) const {
    auto itl = begin(), itr = rhs.begin();
    for (/*null*/; itl != end() && itr != rhs.end(); ++itl, ++itr) {
        if (*itl > *itr)
            return false;
        else if (*itl < * itr)
            return true;
    }
    if (itl == end() && itr != rhs.end())
        return true;
    else
        return false;
}
bool operator>(const String& rhs) const {
    return !(*this == rhs || *this < rhs);
}
bool operator>=(const String& rhs) const {
    return *this > rhs || *this == rhs;
}
bool operator<=(const String& rhs) const {
    return *this < rhs || *this == rhs;
}

19

20

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

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

21

+= 多一次拷贝操作,效率变低

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

Sales_data& operator+=(const Sales_data& rhs) {
    *this = *this + rhs;
    return *this;
}

22

Sales_data& operator=(const string& s) {
    bookNo = s;
    return *this;
}

23

StrVec& operator=(initializer_list<string>& il) {
    free();
    auto newdata = alloc_n_copy(il.begin(), il.end());
    elements = newdata.first;
    first_free = cap = newdata.second;
    return *this;
}

24

25

26

StrBlob:

string& operator[](size_t index) {
    return (*data)[index];
}
const string& operator[](size_t index) const {
    return (*data)[index];
}

StrBlobPtr:

string& operator[](const size_t index) {
    return (*wptr.lock())[index];
}
const string& operator[](const size_t index) const {
    return (*wptr.lock())[index];
}

StrVec:

string& operator[](const size_t index) {
    return *(elements + index);
}
const string& operator[](const size_t index) const {
    return *(elements + index);
}

String:

char operator[](const size_t index) {
    return *(elements + index);
}
const char operator[](const size_t index) const {
    return *(elements + index);
}

27

StrBlobPtr& operator++() {
    check(curr, "increment past end of StrBlobPtr");
    ++curr;
    return *this;
}
StrBlobPtr& operator++(int) {
    StrBlobPtr ret = *this;
    ++*this;
    return ret;
}
StrBlobPtr operator--() {
    --curr;
    check(curr, "decrement past begin of StrBlobPtr");
    return *this;
}
StrBlobPtr operator--(int) {
    StrBlobPtr ret = *this;
    --*this;
    return ret;
}

28

类内的友元声明略。

StrBlobPtr operator+(const StrBlobPtr& p, const int n) {
	StrBlobPtr ret = p;
	ret.check(ret.curr + n, "index overflow");
	ret.curr += n;
	return ret;
}

StrBlobPtr operator+(const int n, const StrBlobPtr& p) {
	StrBlobPtr ret = p;
	ret.check(ret.curr + n, "index overflow");
	ret.curr += n;
	return ret;
}

StrBlobPtr operator-(const StrBlobPtr& p, const int n) {
	StrBlobPtr ret = p;
	ret.check(ret.curr - n, "index overflow");
	ret.curr -= n;
	return ret;
}

StrBlobPtr operator-(const int n, const StrBlobPtr& p) {
	StrBlobPtr ret = p;
	ret.check(ret.curr - n, "index overflow");
	ret.curr -= n;
	return ret;
}

29

因为递增递减运算符需要修改自身状态

30

StrBlobPtr:

string& operator*() const {
    auto p = check(curr, "dereference past end");
    return (*p)[curr];
}
string* operator->() const {
    return &this->operator*();
}

ConstStrBlobPtr:

class ConstStrBlobPtr {
public:
	ConstStrBlobPtr() : curr(0) { }
	ConstStrBlobPtr(const StrBlob& a, size_t sz = 0) :
		wptr(a.data), curr(sz) { }

	const string& operator*() const {
		auto p = check(curr, "dereference past end");
		return (*p)[curr];
	}
	const string* operator->() const {
		return &this->operator*();
	}

private:
	shared_ptr<vector<string>> check(size_t i, const string& msg) const;

	weak_ptr<vector<string>> wptr;
	size_t curr;
};

31

因为这个类的数据成员都是内置类型或者标准库中的类,使用编译器合成的拷贝成员就可以实现正确的语义,不用自己定义。

32

class StrBlobPtrPtr {
public:
	StrBlobPtrPtr() : pointer(nullptr) { }
	StrBlobPtrPtr(StrBlobPtr& p) : pointer(&p) { }

	StrBlobPtr* operator->() const {
		return pointer;
	}

private:
	StrBlobPtr* pointer;
};

33

0 个或者多个

34

#include <iostream>
using namespace std;

template <class T>
class IfThenElse {
public:
	T operator()(bool first, T second, T third) {
		return first ? second : third;
	}
};

int main()
{
	IfThenElse<int> ite;
	bool flag = true;
	int a = 3, b = 5;
	cout << ite(flag, a, b) << endl;
	cout << ite(!flag, a, b) << endl;
	return 0;
}

35

class PrintString {
public:
	string operator()(istream& is) {
		string ret;
		is >> ret;
		return is ? ret : string();
	}
};

36

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

class GetString {
public:
	string operator()(istream& is) {
		string ret;
		is >> ret;
		return is ? ret : string();
	}
};

int main()
{
	vector<string> inputs;
	GetString gs;
	string buffer;
	while (true) {
		buffer = gs(cin);
		if (buffer != string())
			inputs.push_back(buffer);
		else
			break;
	}
	for (auto& s : inputs)
		cout << s << endl;
	return 0;
}

37

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

template<class T>
class IsEqual {
public:
	IsEqual(T t) : target(t) { }

	bool operator()(const T& obj) {
		return obj == target;
	}

private:
	T target;
};

int main()
{
	vector<int> vec{1, 2, 3, 4, 5, 5, 6, 9, 6, 5, 5, 6};
	IsEqual<int> ie(5);
	replace_if(vec.begin(), vec.end(), ie, 10);
	for (auto n : vec)
		printf("%d ", n);
	return 0;
}

输出结果:

1 2 3 4 10 10 6 9 6 10 10 6

38

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

class checkLength {
public:
	checkLength(size_t t) : target(t) { }

	bool operator()(const string& s) {
		return s.size() == target;
	}

private:
	size_t target;
};

int main()
{
	vector<string> words;
	string buffer;
	while (cin >> buffer) {
		words.push_back(buffer);
	}
	for (int len = 1; len <= 10; ++len) {
		checkLength cl(len);
		int cnt = 0;
		for (const string& s : words) {
			if (cl(s))
				++cnt;
		}
		printf("length %d: %d word(s)\n", len, cnt);
	}
	return 0;
}

39

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

class checkLengthLess {
public:
	checkLengthLess(size_t t) : target(t) { }

	bool operator()(const string& s) {
		return s.size() < target;
	}

private:
	size_t target;
};

int main()
{
	vector<string> words;
	string buffer;
	while (cin >> buffer) {
		words.push_back(buffer);
	}
	checkLengthLess cll(10);
	int cnt = 0;
	for (const string& s : words) {
		if (cll(s))
			++cnt;
	}
	printf("length less than 10: %d word(s)\n", cnt);
	printf("length gerater than or equal to 10: %d word(s)\n", words.size() - cnt);
	return 0;
}

40

class LessStringSize {
public:
	bool operator()(const string& a, const string& b) {
		return a.size() < b.size();
	}
};

class CheckLengthGreaterEqual {
public:
	CheckLengthGreaterEqual(size_t t) : target(t) { }

	bool operator()(const string& s) {
		return s.size() >= target;
	}

private:
	size_t target;
};

class PrintString {
public:
	void operator()(const string& s) {
		cout << s << " ";
	}
};

void biggies(vector<string>& words, vector<string>::size_type sz) {
	stable_sort(words.begin(), words.end(), LessStringSize());
	auto wc = find_if(words.begin(), words.end(), CheckLengthGreaterEqual(sz));
	auto count = words.end() - wc;
	cout << count << " " << make_plural(count, "word", "s")
		<< " of length " << sz << "or longer" << endl;
	for_each(wc, words.end(), PrintString());
	cout << endl;
}

41

lambda 提供了函数对象的匿名简便写法。对我来说如果一个函数对象只需要使用一次,特别是在调用标准库的泛型算法的时候,使用 lambda 很方便;如果需要多次调用一个函数对象,或者需要保存复杂的状态,使用类在语义和可读性上更好一点

42

a.

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
using namespace std::placeholders;

int main() {
	vector<int> vec{ 500, 600, 700, 800, 1100, 1200, 1300 };
	int cnt = count_if(vec.begin(), vec.end(),
		bind(greater<int>(), _1, 1024));
	cout << cnt << endl;
	return 0;
}

b.

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
using namespace std::placeholders;

int main()
{
	vector<string> vec{ "pooh", "pooh", "pooh", "pooooh", "pooh", "pooh", "pooh" };
	auto it = find_if_not(vec.begin(), vec.end(),
		bind(equal_to<string>(), _1, "pooh"));
	cout << *it << endl;
	return 0;
}

c.

参考了 传送门 的写法

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
using namespace std::placeholders;

int main() {
	vector<int> vec{ 500, 600, 700, 800, 1100, 1200, 1300 };
	//for_each(vec.begin(), vec.end(),
	//	[](int& num) { 
	//		num = bind(multiplies<int>(), _1, 2)(num);
	//	});
	// 上面是自己写的,下面是更好的写法
	transform(vec.begin(), vec.end(), vec.begin(), bind(multiplies<int>(), _1, 2));
	for_each(vec.begin(), vec.end(), [](const int n) { cout << n << " "; });
	cout << "\n";
	return 0;
}

43

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
using namespace std::placeholders;

int main() {
	vector<int> vecA{ 500, 600, 700, 800, 1100, 1200, 1300 };
	vector<int> vecB{ 500, 600, 700, 800, 1100, 1200, 1300, 15 };
	bool flagA = none_of(vecA.begin(), vecA.end(), bind(modulus<int>(), _1, 10));
	bool flagB = none_of(vecB.begin(), vecB.end(), bind(modulus<int>(), _1, 10));
	cout << flagA << endl;
	cout << flagB << endl;
	return 0;
}

44

#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
#include <functional>
using namespace std;

int main() {
	map<string, function<double(double, double)>> opToFuncs = {
		{"+", plus<double>()},
		{"-", minus<double>()},
		{"*", multiplies<double>()},
		{"/", divides<double>()},
	};
	double a, b;
	string op;
	while (cin >> a >> op >> b) {
		printf("%g %s %g = %g\n", a, op.c_str(), b, opToFuncs[op](a, b));
	}
	return 0;
}

45

explicit operator string() const {
    return bookNo;
}
explicit operator double() const {
    return revenue;
}

46

不应该,可以写一个成员函数来获得数据成员的值。如果确实需要转换运算符,那就声明为 explicit 的,防止产生歧义,用户在需要转换的时候显式调用

47

operator const int();
operator int() const;

第一行的转换运算符含义是:可以将对象转换成 const int 类型,且转换过程中可能会改变带转换对象的内容

第二行的转换运算符含义是:可以将对象转换成 int 类型,且转换过程中不会改变带转换对象的内容

48

49

50

int ex1 = ldObj;

可能 LongDouble 到 double 到 int,也可能 LongDouble 到 float 到 int。所以这个初始化是错误的,会产生二义性

float ex2 = ldObj;

LongDouble 到 float,初始化正确

51

P219 写出了函数重载匹配的优先级:

  1. 精确匹配
  2. const 转换
  3. 类型提升
  4. 算术类型转换或指针转换
  5. 类类型转换

可以看到类类型转换的优先级是最低的,所以这里会调用 void calc(int);

52

ld = si + ld;

不合法,二义性错误,可以匹配内置的 operator+(int, double) 或者内置的 operator+(int, float)

ld = ld + si;

合法,匹配的是 LongDouble operator+(const SmallInt& rhs)

53

不合法,二义性错误,可以匹配内置的算术类型加法(左操作数 SmallInt 类型类型可以类类型转换成 int),也可以匹配两个 SmallInt 类型的加法(右操作数 double 类型算术类型转换成 int 再类类型转换成 SmallInt)

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-24 10:21:36  更:2021-09-24 10:22:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 21:21:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码