C++ Primer课后习题解答(第十四章)

Exercises Section 14.1

Ex14.1

不同点:重载操作符必须至少有一个类类型或枚举类型的操作数;重载操作符不保证操作数的求值顺序。
相同点:有相同的优先级和结合性,操作数的数目不变。

Ex14.2

class Sales_data
{
	friend ostream &operator<<(ostream &, const Sales_data &);
	friend istream &operator>>(istream &, Sales_data &);
public:
	Sales_data &operator+=(const Sales_data &);
	// 其他公有成员、私有成员和友元函数不变
};

Sales_data operator+(const Sales_data &, const Sales_data &);

Ex14.3

vector<string> svec1, svec2;
a) "cobble" == "stone"		// 内置类型 ==
b) svec1[0] == svec2[0]		// 使用 string 的 ==
c) svec1 == svec2			// 使用 vector 的 == 
d) svec1[0] == "stone"		// 使用 string 的 ==

Ex14.4

a) %	// 定义为非成员
b) %=	// 最好被定义为成员
c) ++	// 定义为成员
d) ->	// 定义为成员
e) <<	// 定义为非成员
f) &&	// 定义为非成员
g) ==	// 定义为非成员
h) ()	//  定义为成员

Ex14.5

class Book
{
	friend std::ostream &operator<<(std::ostream &, const Book &);
	friend std::istream &operator>>(std::istream &, Book &);
public:
    Book() = default;
    Book(const std::string s) : bookNo(s) {}
    Book(const std::string s, const std::String n, const double p) : BookNo(s), author_name(n), revenue(p) {}

private:
    std::string bookNo;
    std::string author_name;
    double price;
};

std::ostream &operator<<(std::ostream &os, const Book &b)
{
	os << b.bookNo << " " << b.author_name << " " << b.price;
	return os;
}

std::istream &operator>>(std::istream &is, Book &b)
{
	is >> b.bookNo >> b.author_name >> b.price;
	if (!is)
		b = Book();
	return is;
}

Exercises Section 14.2.1

Ex14.6

ostream &operator<<(ostream &os, const Sales_data &item)
{
	os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
	return os;
}

Ex14.7

ostream &operator<<(osteam &os, const string &s)
{
	return print(os, s);
}

Ex14.8

Ex14.5

Exercises Section 14.2.2

Ex14.9

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

Ex14.10

a) 0-201-99999--9 10 24.95	// 正常输入
b) 10 24.95 0-210-99999-9	// 输入类型对应错误,最后会调用默认构造函数

Ex14.11

// 如果输入的类型对应错误,那么就无法处理错误情况
// 上个练习中 a 情况正常,b 就会发生错误
isteam &operator>>(istream &in, Sales_data &s)
{
	double price;
	in >> s.bookNo >> s.units_sold >> price;
	s.revenue = s.units_sold * price;
	return in;
}

Ex14.12

Ex14.5

Exercises Section 14.3

Ex14.13

还可以定义减法运算符

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

Sales_data operator-(const Sales_data &lhs, const Sales_data &rhs)
{
	Sales_data sub = lhs;
	sub -= rhs;
	return sub;
}

Ex14.14

代码复用

Ex14.15

定义的 Book 类不需要算术运算符

Exercises Section 14.3.1

Ex14.16

class StrBolb
{
	friend bool operator==(const StrBolb &, const StrBolb &);
	friend bool operator!=(const StrBolb &, const StrBolb &);
	// 其他公有成员、私有成员和友元函数不变
};

bool operator==(const StrBolb &lhs, const StrBolb &rhs)
{
	return lhs.data == rhs.data;
}

bool operator!=(const StrBolb &lhs, const StrBolb &rhs)
{
	return !(lhs == rhs);
}
class StrBlobPtr
{
	friend bool operator==(const StrBlobPtr &, const StrBlobPtr &);
	friend bool operator!=(const StrBlobPtr &, const StrBlobPtr &);
	// 其他公有成员、私有成员和友元函数不变
};

bool operator==(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
	return lhs.curr = rhs.curr &&
		   lhs.wptr.lock() == rhs.wptr.lock();
}

bool operator!=(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
	return !(lhs == rhs);
}
class StrVec
{
	friend bool operator==(const StrVec &, const StrVec &);
	friend bool operator!=(const StrVec &, const StrVec &);
	// 其他公有成员、私有成员和友元函数不变
};

bool operator==(const StrVec &lhs, const StrVec &rhs)
{
	if (lhs.size() != rhs.size())
		return false;
	for (auto it1 = lhs.begin(). it2 = rhs.begin(); it1 != lhs.end() && it2 != rhs.end(); ++it1, ++it2)
	{
		if (*it1 != *it2)
			return false;
	}
	return true;
}

bool operator!=(const StrVec &lhs, const StrVec &rhs)
{
	return !(lhs == rhs);
}

Ex14.17

class Book
{
	friend bool operator==(const Book &, const Book &);
	friend bool operator!=(const Book &, const Book &);
	// 其他公有成员、私有成员和友元函数不变
};

bool operator==(const Book &lhs, const Book &rhs)
{
	return lhs.bookNo == rhs.bookNo &&
		   lhs.author_name == rhs.author_name &&
		   lhs.price == rhs.price;
}

bool operator!=(const Book &lhs, const Book &rhs)
{
	return !(lhs == rhs);
}

Exercises Section 14.3.2

Ex14.18

class StrBolb
{
	friend bool operator<(const StrBolb &, const StrBolb &);
	friend bool operator<=(const StrBolb &, const StrBolb &);
	friend bool operator>(const StrBolb &, const StrBolb &);
	friend bool operator>=(const StrBolb &, const StrBolb &);
	// 其他公有成员、私有成员和友元函数不变
};

bool operator<(const StrBolb &lhs, const StrBolb &rhs)
{
	return *lhs.data < *rhs.data;
}

bool operator<=(const StrBolb &lhs, const StrBolb &rhs)
{
	return *lhs.data <= *rhs.data;
}

bool operator>(const StrBolb &lhs, const StrBolb &rhs)
{
	return *lhs.data > *rhs.data;
}

bool operator>=(const StrBolb &lhs, const StrBolb &rhs)
{
	return *lhs.data >= *rhs.data;
}
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 &);
	// 其他公有成员、私有成员和友元函数不变
};

bool operator<(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
	auto l = lhs.wptr.lock(), r = rhs.wptr.lock();
	if (l == r)
	{
		if (!r)
			return false;
		return lhs.curr < rhs.curr;
	}
	else 
		return false;
}

bool operator<=(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
	auto l = lhs.wptr.lock(), r = rhs.wptr.lock();
	if (l == r)
	{
		if (!r)
			return false;
		return lhs.curr <= rhs.curr;
	}
	else 
		return false;
}

bool operator>(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
	auto l = lhs.wptr.lock(), r = rhs.wptr.lock();
	if (l == r)
	{
		if (!r)
			return false;`在这里插入代码片`
		return lhs.curr > rhs.curr;
	}
	else 
		return false;
}

bool operator>=(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
	auto l = lhs.wptr.lock(), r = rhs.wptr.lock();
	if (l == r)
	{
		if (!r)
			return false;
		return lhs.curr >= rhs.curr;
	}
	else 
		return false;
}
class StrVec
{
	friend bool operator<(const StrVec &, const StrVec &);
	friend bool operator<=(const StrVec &, const StrVec &);
	friend bool operator>(const StrVec &, const StrVec &);
	friend bool operator>=(const StrVec &, const StrVec &);
	// 其他公有成员、私有成员和友元函数不变
};

bool operator<(const StrVec &lhs, const StrVec &rhs)
{
	for (auto it1 = lhs.begin(), it2 = rhs.begin(); it1 != lhs.end(), it2 != rhs.end(); ++it1, ++it2)
	{
		if (*it1 < *it2)
			return true;
		if (*it1 > *it2)
			return false;
	}
	if (lhs.size() < rhs.size())
		return true;
	return false;
}

bool operator<=(const StrVec &lhs, const StrVec &rhs)
{
	for (auto it1 = lhs.begin(), it2 = rhs.begin(); it1 != lhs.end(), it2 != rhs.end(); ++it1, ++it2)
	{
		if (*it1 <= *it2)
			return true;
	}
	if (lhs.size() <= rhs.size())
		return true;
	return false;
}

bool operator>(const StrVec &lhs, const StrVec &rhs)
{
	for (auto it1 = lhs.begin(), it2 = rhs.begin(); it1 != lhs.end(), it2 != rhs.end(); ++it1, ++it2)
	{
		if (*it1 > *it2)
			return true;
		if (*it1 < *it2)
			return false;
	}
	if (lhs.size() > rhs.size())
		return true;
	return false;
}

bool operator>=(const StrVec &lhs, const StrVec &rhs)
{
	for (auto it1 = lhs.begin(), it2 = rhs.begin(); it1 != lhs.end(), it2 != rhs.end(); ++it1, ++it2)
	{
		if (*it1 >= *it2)
			return true;
	}
	if (lhs.size() >= rhs.size())
		return true;
	return false;
}

Ex14.19

不需要,书本进行比较没有多大意义。

Exercises Section 14.4

Ex14.20

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

Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs)
{
	Sales_data sum = lhs;
	sum += rhs;
	return sum;
}

Ex14.21

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

Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs)
{
	Sales_data sum = lhs;
	sum.units_sold += rhs.units_sold;
	sum.revenue += rhs.revenue;
	return sum;
}

operator+ 需要被定义为友元,可读性差。

Ex14.22

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

Ex14.23

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

Ex14.24

使用合成的拷贝赋值运算符即可

Ex14.25

定义一个赋值运算符,把 string 赋值给 Book

Book &Book::operator=(const string &s)
{
	istringstream in(s);
	in >> bookNo >> author_name >> price;
	if (!in)
		*this = Book();
	return *this;
}

Exercises Section 14.5

Ex14.26

class StrBlob
{
public:
	std::string & operator[](std::size_t n) { check(n, "out of range"); return (*data)[n]; }
	const std::string & operator[](std::size_t n) const { check(n, "out of range"); return (*data)[n]; }
	// 其他公有成员、私有成员和友元函数不变
};
class StrBlobPtr
{
public:
	std::string & operator[](std::size_t n) { auto p = check(n, "out of range"); return (*p)[n]; }
	const std::string & operator[](std::size_t n) const { auto p = check(n, "out of range"); return (*p)[n]; }
	// 其他公有成员、私有成员和友元函数不变
};
class StrVec
{
public:
	std::string & operator[](std::size_t n) { return elements[n]; }
	const std::string & operator[](std::size_t n) const; { return elements[n]; }
	// 其他公有成员、私有成员和友元函数不变
};

Exercises Section 14.6

Ex14.27

class StrBlobPtr
{
public:
	StrBlobPtr & operator++();
	StrBlobPtr & operator--();
	StrBlobPtr operator++(int);
	StrBlobPtr operator--(int);
	// 其他公有成员、私有成员和友元函数不变
};

StrBlobPtr &StrBlobPtr::operator++()
{
	check(curr, "increment past end of StrBlobPtr");
	++curr;
	return *this;
}

StrBlobPtr &StrBlobPtr::operator--()
{
	--curr;
	check(curr, "decrement past begin of StrBlobPtr");
	reurn *this;
}

StrBlobPtr StrBlobPtr::operator++(int)
{
	StrBlobPtr ret = *this;
	++*this;
	return ret;
}

StrBlobPtr StrBlobPtr::operator--(int)
{
	StrBlobPtr ret = *this;
	--*this;
	return ret;
}

Ex14.28

class StrBlobPtr
{
public:
	StrBlobPtr & operator+=(const size_t &);
	StrBlobPtr & operator-=(const size_t &);
	// 其他公有成员、私有成员和友元函数不变
};

StrBlobPtr &StrBlobPtr::operator+=(const size_t &n)
{
	check(curr, "increment past end of StrBlobPtr");
	curr += n;
	return *this;
}

StrBlobPtr &StrBlobPtr::operator-=(const size_t &n)
{
	curr -= n;
	check(curr, "decrement past begin of StrBlobPtr");
	return *this;
}

Ex14.29

递增和递减都会改变对象的值,故而不能能定义为const。

Exercises Section 14.7

Ex14.30

class StrBlobPtr
{
public:
	std::string & operator*() const 
	{ 
		auto p = check(curr, "dereference past end");
	  	return (*p)[curr]; 
	}
	std::string * operator->() const
	{	
		return & this->operator*();
	}
	// 其他公有成员、私有成员和友元函数不变
};
class ConstStrBlobPtr
{
public:
	const std::string & operator*() const 
	{ 
		auto p = check(curr, "dereference past end");
	  	return (*p)[curr]; 
	}
	const std::string * operator->() const
	{	
		return & this->operator*();
	}
	// 其他公有成员、私有成员和友元函数不变
};

Ex14.31

因为 StrBlobPtr 类对于拷贝构造、赋值操作和析构都不需要执行另外的内容,故而使用编译器合成的即可。

Ex14.32

class PointStr
{
public:
	std::string * operator->()
	{
		return p->operator->();
	}
private:
	StrBlobPtr *p;
};

Exercises Section 14.8

Ex14.33

0个或多个

Ex14.34

class ReturnPara
{
public:
	ReturnPara() = default;
	ReturnPara(int i, int j, int k): a(i), b(j), c(k) { }
	int operator()(const int &i, const int &j, const int &k)  const
	{
		if (i)
			return j;
		else 
			return k;
	}
private:
	int a;
	int b;
	int c;
}

Ex14.35

class ReadString
{
public:
	ReadString(istream &is = cin): in(is) { }
	string operator()()
	{
		string temp;
		if (!getline(in, temp))
			temp = "";
		return temp;
	}
private:
	istream &in;
};

Ex14.36

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>

using namespace std;

class ReadString
{
public:
	ReadString(istream &is = cin): in(is) { }
	string operator()()
	{
		string temp;
		if (!getline(in, temp))
			temp = "";
		return temp;
	}
private:
	istream &in;
};

int main()
{
	vector<string> vec;
	string line;
	while (true)
	{
		string line = ReadString()();
		if (!line.empty())
			vec.push_back(line);
		else 
			break;
	}
	for_each(vec.begin(), vec.end(), [](string &s) { cout << s << endl; });

	system("pause");
	return 0;
}

Ex14.37

class CompareString
{
public:
	CompareString(string s = string()): str(s) { }
	bool operator()(string &s) const { return s == str; }
private:
	string str;
};

Exercises Section 14.8.1

Ex14.38

#include<iostream>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<string>

using namespace std;

class CompareString
{
public:
	CompareString(size_t n): sz(n) { }
	bool operator()(const string &s) const
	{
		return s.size() == sz;
	}

private:
	size_t sz;
}

int main(int argc, char *argv[])
{
	vector<string> words;
	string word;
	ifstream in(argv[1]);
	string line;
	while (getline(in, line))
	{
		istringstream iss(line);
		while (iss >> word)
		{
			if (ispunct(word[0]))
				word.erase(0, 1);
			if (ispunct(word[word.size() - 1]))
				word.pop_back();
			words.push_back(word);
			cout << word << " ";
		}
		cout << endl;
	}

	for (size_t i = 1; i != 11; ++i)
	{
		int cnt = 0;
		auto wc = words.begin();
		while (wc != words.end())
		{
			wc = find_if(wc, words.end(), CompareString(i));
			if (wc != words.end())
			{
				cout << *wc << " ";
				++wc;
				++cnt;
			}
		}
		cout << endl;
		cout << "length " << i << " has " << cnt << endl;
	}
	system("pause");
	return 0;
}

Ex14.39

#include<iostream>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<string>

using namespace std;

class BoundSize
{
public:
	BoundSize(size_t b, size_t t): bottom(b), top(t) { }
	bool operator()(const string &s) const
	{
		return s.size() >= bottom && s.size() <= top;
	}

private:
	size_t bottom;
	size_t top;
}

class LongerSize
{
public:
	LongerSize(size_t s): sz(s) { }
	bool operator()(const string &s) const { return s.size() >= sz; }
private:
	size_t sz;
}



int main(int argc, char *argv[])
{
	vector<string> words;
	string word;
	ifstream in(argv[1]);
	string line;
	while (getline(in, line))
	{
		istringstream iss(line);
		while (iss >> word)
		{
			if (ispunct(word[0]))
				word.erase(0, 1);
			if (ispunct(word[word.size() - 1]))
				word.pop_back();
			words.push_back(word);
			cout << word << " ";
		}
		cout << endl;
	}

	for (size_t i = 1; i != 11; ++i)
	{
		int cnt = 0;
		auto wc = words.begin();
		while (wc != words.end())
		{
			wc = find_if(wc, words.end(), BoundSize(1, 9));
			if (wc != words.end())
			{
				cout << *wc << " ";
				++wc;
				++cnt;
			}
		}
		cout << endl;
		cout << "length 1 - 9 has " << cnt << endl;
	}

	cnt = 0;
	wc = words.begin();
	while (wc != words.end())
	{
		wc = find_if(wc, words.end(), LongerSize(10));
		if (wc != words.end())
		{
			cout << *wc << " ";
			++wc;
			++cnt;
		}
	}
	cout << endl;
	cout << "Length longer than 10 has " << cnt << endl;
	system("pause");
	return 0;
}

Ex14.40

#include <iostream>
#include <algorithm>
#include <vector>
#include <fstream>
#include <sstream>
 
using namespace std;
 
class IsShorter 
{
public:
	bool operator()(const string &s1, const string &s2) { return s1.size() < s2.size(); }
};
 
class LongerThan 
{
public:
	LongerThan(size_t sz): sz(sz) { } 
	bool operator()(const string &s) { return s.size() > sz; }
private:
	size_t sz;
};
 
class PrintStr 
{
public:
	void operator()(const string &s) { cout << s << " "; }
};
 
void elimDups(vector<string> &words)
{
	sort(words.begin(), words.end());
	auto end_unique = unique(words.begin(), words.end());
	words.erase(end_unique, words.end());
}
 
void biggies(vector<string> &words, vector<string>::size_type sz)
{
	elimDups(words);
	IsShorter is;
	stable_sort(words.begin(), words.end(), is);
	
	LongerThan longer(sz);
	auto wc = find_if(words.begin(), words.end(), longer);
	auto cnt = words.end() - wc;
	
	PrintStr ps;
	for_each(wc, words.end(), ps);
			 
	cout << endl;
}
 
int main(int argc, char *argv[])
{
	ifstream in(argv[1]);
	string line, word;
	vector<string> words;
	
	while (getline(in, line)) 
	{
		istringstream text(line);
		while (text >> word)
			words.push_back(word);
	}
	
	biggies(words, 4);
	
	system("pause");
	return 0;
}

Ex14.41

lambda通过匿名的函数对象实现,可看作函数对象的简化方式;当函数只用一次,可以用lambda实现,需要多次使用则用函数对象。

Exercises Section 14.8.2

Ex14.42

#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>

using namespace std;
using std::placeholders::_1;

int main()
{
	vector<int> v1 = {1024, 2025, 510, 4568};
	vector<int> v2 = {2, 4, 6, 8};
	vector<string> v3 = {"pooh", "pool", "fool"};

	auto wc = count_if(v1.begin(), v1.end(), bind(greater<int>(), _1, 1024));
	auto iter = find_if(v3.begin(), v3.end(), bind(not_equal_to<string>(), _1, "pooh"));
	transform(v2.begin(), v2.end(), v2.begin(), bind(multiplies<int>(), _1, 2));
	cout << wc << " " << *iter << endl;;
	for (auto &i : v2)
		cout << i << " ";
	cout << endl;

	system("pause");
	return 0;
}

Ex14.43

#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>

using namespace std;
using std::placeholders::_1;

bool DivByAll(const vector<int> &vec, int div)
{
	return !count_if(vec.begin(), vec.end(), bind(modulus<int>(), _1, div));
}

int main()
{
	vector<int> v1 = {1024, 2025, 510, 4568};
	vector<int> v2 = {2, 4, 6, 8};

	cout << DivByAll(v1, 3) << " " << DivByAll(v2, 2) << endl;
	system("pause");
	return 0;
}

Exercises Section 14.8.3

Ex14.44

#include<iostream>
#include<map>
#include<functional>
#include<string>
#include<algorithm>

using namespace std;

int add(int i, int j)
{
	return i + j;
}

class divide
{
public:
	int operator()(int denominator, int divisor)
	{
		return denominator / divisor;
	}
};

auto mod = [] (int i, int j) { return i % j; };

map<string, function<int(int, int)>> binops = 
{
	{"+", add},
	{"-", std::minus<int>()},
	{"/", divide()},
	{"*", [](int i, int j) { return i * j; }},
	{"%", mod}
};


int main()
{
	int lhs, rhs;
	string op;
	cin >> lhs >> op >> rhs;
	cout << "result: " << binops[op](lhs, rhs) << endl;
	system("pause");
	return 0;
}

Exercises Section 14.9.1

Ex14.45

class Sales_data
{
public:
	operator string() const { return bookNo; }
	operator ddouble() const { return revenue; }
	// 其他公有成员、私有成员、友元不变
};

Ex14.46

不应定义以上两种类型转换,只有bookNo, units_sold 和 revenue 三者组合才有意义;应该定义成 explicit 的,防止进行默认的转换。

Ex14.47

struct Integral
{
	operator const int();		// 将 Integral 转换为 const int
	operator int() const;		// 将 const Integral 转换为 int
};

Ex14.48

定义的是 Book 类,可以定义一个 bool 类型的转换运算符,用来检查书籍是否有效;应该声明为 explicit,防止自动转换引发错误。

Ex14.49

class Book
{
public:
	operator bool();
	// 其他公有成员、私有成员、友元不变
}

Exercises Section 14.9.2

Ex14.50

// ex1: LongDouble::operator double() or LongDouble::operator float() 产生二义性
// ex2: LongDouble::operator float()
struct LongDouble
{
	LongDouble(double = 0.0);
	operator double();
	operator float();
};
LongDouble ldObj;
int ex1 = ldObj;
float ex2 = ldObj;

Ex14.51

/* void calc(int),将 double 转换为 int,是标准类型转换
 * 而void calc(LongDouble) 转换为用户自定义类型
 * 标准类型优先
 * 故而 calc(dval) 会调用 void calc(int)
 */
void calc(int);		
void calc(LongDouble);
double dval;
calc(dval);	

Exercises Section 14.9.3

Ex14.52

class SmallInt
{
	friend SmallInt operator+(const SmallInt &, const SmallInt &);
public:
	SmallInt(int = 0);
	operator int() const { return val; }
private:
	std::size_t val;
};

struct LongDouble
{
	LongDouble operator+(const SmallInt &);
	LongDouble(double = 0.0);
	operator double();
	operator float();
};

LongDouble operator+(LongDouble &, double);

SmallInt si;
LongDouble ld;
ld = si + ld;	
ld = ld + si;

对于 ld = si + ld
LongDouble 类型无法转换为 SmallInt 类型,故而 SmallInt 的 friend operator+ 不适用;
SmallInt 类型无法转换为 LongDouble 类型,LongDouble 的成员 operator+ 和非成员 operator+ 都不适用;
SmallInt 可转换为 int,LongDouble 可转换为 double 或 float,成员operator+ 和非成员 operator+都适用,产生二义性。

对于ld = ld + si
LongDouble 无法转换为 SmallInt,SmallInt 的 friend operator+ 不适用,LongDouble成员 operator+(const SmallInt &) 精确匹配;
SmallInt 无法转换为 LongDouble,故 LongDouble 的成员 operator+ 和非成员 operator+ 都不适用;
故而使用LongDouble成员 operator+(const SmallInt &)

Ex14.53

class SmallInt
{
	friend SmallInt operator+(const SmallInt &, const SmallInt &);
public:
	SmallInt(int = 0);
	operator int() const { return val; }
private:
	std::size_t val;
};

SmallInt sl;
double d = sl + 3.14;

友元 operator+ 适用,可以将 3.14 转换为 int 类型,然后再从 int 类型转换为 SmallInt 类型;
也可以将 sl 转换为 int 类型,故而产生二义性。

更改如下:

SmallInt sl;
double d = sl + SmallInt(3.14);
posted @   astralcon  阅读(58)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示