14.1 重载运算符与内置运算符有什么相同点和不同点
相同:
- 有相同的优先级和关联性
不同:
- 重载的运算符大多是类的成员或至少有一个类类型的参数
- 可以直接调用重载的运算符来实现自定义的操作,但这些操作一定要与内置操作符具有关联性
14.2 为Sales_data类编写重载的输入输出,加法,复合赋值运算符
istream& operator>>(istream& is, Sales_data& rhs)
{
double price = 0.0;
is >> rhs.bookNo >> rhs.units_sold >> price;
if (is)
rhs.revenue = rhs.units_sold*price;
else //如果发生了IO错误,运算符将给定对象重置为空的状态
rhs = Sales_data();
return is;
}
ostream& operator<<(ostream& os, const Sales_data& rhs)
{
os << rhs.isbn() << " " << rhs.units_sold << " " << rhs.revenue << " "
<< rhs.avg_price();
return os;
}
Sales_data operator+(const Sales_data& lhs,const Sales_data& rhs)
{
Sales_data sum = lhs;
sum += rhs; //复合运算符已经重载,所以直接用
return sum;
}
Sales_data& Sales_data::operator+=(const Sales_data& rhs) //复合运算符执行实际工作
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
14.3
- 两者都不是(字符串常量类型为const char[],不是string)
- string
- vector
- string
14.4
(a)对称运算符。因此,非成员
(b)改变物体的状态。因此,成员
(c)改变物体的状态。因此,成员
(d)=()[] - >必须是成员
(e)非会员
(f)对称的非会员
(g)对称,非成员
(h)=()[] - >必须是成员
14.5 略
14.6 参考14.2
14.7
需要在声明为类的友元
ostream& operator<<(ostream& os, const String& rhs)
{
for (auto it = rhs.elements; it != rhs.first_free; ++it)
os << *it;
return os;
}
14.8 略
14.9 参考14.2
14.10
- 正确的输入
- 输入格式错误,输出结果里的数据混乱
14.11 没有检查输入流的状态
14.12 略
14.13 nothing
14.14
拿Sales_data来举例,简单来说就是如果用复合运算符去实现算术运算符比用算术运算符去实现复合运算符少使用了临时对象,减少了不必要的内存开销
Sales_data& Sales_data::operator+=(const Sales_data &rhs)
{
Sales_data old_data = *this;
*this = old_data + rhs;
return *this;
}
Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs) //加号运算符执行实际工作
{ //此种方式的定义:复合和加号运算符都使用了不必要的临时对象
Sales_data sum; 增加内存开销
sum.units_sold = lhs.units_sold + rhs.units_sold;
sum.revenue = lhs.revenue + rhs.revenue;
return sum;
}
14.15 略
14.16
同样需要声明为类的友元
bool operator==(const StrBlob& lhs, const StrBlob& rhs)
{
return (*lhs.data==*rhs.data);
}
bool operator!=(const StrBlob& lhs, const StrBlob& rhs)
{
return !(lhs == rhs);
}
bool operator==(const String& lhs, const String& rhs)
{
return (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.begin(),rhs.begin()));
}
bool operator!=(const String& lhs, const String& rhs)
{
return !(lhs == rhs);
}
bool operator==(const StrVec& lhs, const StrVec& rhs)
{
return (lhs.size() == rhs.size() && std::equal(lhs.elements, lhs.first_free, rhs.elements));
}
bool operator!=(const StrVec& lhs, const StrVec& rhs)
{
return !(lhs == rhs);
}
14.17 略
14.18
bool operator<(const StrBlob& lhs, const StrBlob& rhs)
{
return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(),
rhs.data->begin(), rhs.data->end());
}
bool operator>(const StrBlob& lhs, const StrBlob& rhs)
{
return rhs < lhs;
}
bool operator<=(const StrBlob& lhs, const StrBlob& rhs)
{
return !(rhs < lhs);
}
bool operator>=(const StrBlob& lhs, const StrBlob& rhs)
{
return !(rhs > lhs);
}
bool operator<(const String& lhs, const String& rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(),
rhs.begin(),rhs.end());
}
bool operator>(const String& lhs, const String& rhs)
{
return rhs < lhs;
}
bool operator<=(const String& lhs, const String& rhs)
{
return !(rhs < lhs);
}
bool operator>=(const String& lhs, const String& rhs)
{
return !(rhs > lhs);
}
bool operator<(const StrVec& lhs, const StrVec& rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), lhs.end());
}
bool operator>(const StrVec& lhs, const StrVec& rhs)
{
return rhs < lhs;
}
bool operator<=(const StrVec& lhs, const StrVec& rhs)
{
return !(rhs < lhs);
}
bool operator>=(const StrVec& lhs, const StrVec& rhs)
{
return !(rhs > lhs);
}
14.19 略
14.20 参考14.2
14.21 参考14.14
14.22
Sales_data& operator=(const string& isbn) { *this = Sales_data(isbn); }
14.23
StrVec& StrVec::operator=(initializer_list<string> lst)
{
free();
auto data = alloc_n_copy(lst.begin(), lst.end());
elements = data.first;
first_free = data.second;
return *this;
}
14.26
string& operator[](size_t n) { return data->at(n); }
const string& operator[](size_t n)const { return data->at(n); }
char& operator[](size_t n) { return elements[n]; }
const char& operator[](size_t n)const { return elements[n]; }
string& operator[](size_t n) { return elements[n]; }
const string& operator[](size_t n)const { return elements[n]; }
14.27
StrBlobPtr& operator++()
{
check(curr, "end of vector");
++curr;
return *this;
}
StrBlobPtr& operator--()
{
--curr;
check(curr, "decrement past begin of StrBlob");
return *this;
}
StrBlobPtr operator++(int)
{
auto ret = *this;
++*this;
return ret;
}
StrBlobPtr operator--(int)
{
auto ret = *this;
--*this;
return ret;
}
14.28
StrBlobPtr operator+(int i)
{
auto ret = *this;
ret.curr += i;
check(ret.curr, "out of range");
return ret;
}
StrBlobPtr operator-(int i)
{
auto ret = *this;
ret.curr -= i;
check(ret.curr, "out of range");
return ret;
}
14.29
递增递减运算符改变对象的状态
14.30
string& operator*()const
{
auto p = check(curr, "out of range");
return (*p)[curr];
}
string* operator->()const
{
return &this->operator*();
}
14.31
编译器合成的足够使用了
14.32
class StrBlobPtr_pointer {
public:
StrBlobPtr_pointer() = default;
StrBlobPtr_pointer(StrBlobPtr* p) : pointer(p) {}
StrBlobPtr& operator*();
StrBlobPtr* operator->();
private:
StrBlobPtr* pointer = nullptr;
};
StrBlobPtr& StrBlobPtr_pointer::operator*()
{
return *(this->pointer);
}
StrBlobPtr* StrBlobPtr_pointer::operator->()
{
return &this->operator*();
}
14.33
256个,详细解释https://stackoverflow.com/questions/21211889/how-many-operands-may-an-overloaded-function-call-operator-take
14.34
struct Test {
int operator()(bool b, int iA, int iB) {
return b ? iA : iB;
}
};
14.35
#include <iostream>
#include <string>
using namespace std;
class PrintString {
public:
PrintString(istream& i ) :is(i){}
string& operator()()
{
if (is >> str)
return str;
else
str = (" ");
return str;
}
private:
string str;
istream& is;
};
int main(int argc, char** argv)
{
PrintString p(cin);
string str = p();
cout << str;
return 0;
}
14.37
#include <iostream>
#include <vector>
#include <algorithm>
class IsEqual {
int value;
public:
IsEqual(int v) : value(v) {}
bool operator()(int elem) { return elem == value; }
};
int main()
{
std::vector<int> vec = {3, 2, 1, 4, 3, 7, 8, 6};
std::replace_if(vec.begin(), vec.end(), IsEqual(3), 5);
for (int i : vec) std::cout << i << " ";
std::cout << std::endl;
}
14.38
include <functional>
#include <algorithm>
#include <fstream>
using namespace std;
class Compare {
public:
Compare(size_t i):val(i){}
bool operator()(const string& str) const
{
return str.size() == val;
}
private:
int val;
};
int main(int argc, char** argv)
{
vector<string> vec{ "c","c++","c#","java","python","go" };
for (int i = 1; i <= 6; ++i)
{
cout << "长度为" << i << "的单词有" << count_if(vec.begin(), vec.end(), Compare(i)) << endl;
}
return 0;
}
14.40
#include <vector>
using std::vector;
#include <string>
using std::string;
#include <iostream>
using std::cout;
using std::endl;
#include <algorithm>
using std::sort;
using std::stable_sort;
using std::for_each;
class ShorterString {
public:
bool operator()(string const& s1, string const& s2) const
{
return s1.size() < s2.size();
}
};
class BiggerEqual {
size_t sz_;
public:
BiggerEqual(size_t sz) : sz_(sz) {}
bool operator()(string const& s) { return s.size() >= sz_; }
};
class Print {
public:
void operator()(string const& s) { cout << s << " "; }
};
string make_plural(size_t ctr, string const& word, string const& ending)
{
return (ctr > 1) ? word + ending : word;
}
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);
stable_sort(words.begin(), words.end(), ShorterString());
auto wc = find_if(words.begin(), words.end(), BiggerEqual(sz));
auto count = words.end() - wc;
cout << count << " " << make_plural(count, "word", "s") << " of length "
<< sz << " or longer" << endl;
for_each(wc, words.end(), Print());
cout << endl;
}
int main()
{
vector<string> vec{"fox", "jumps", "over", "quick", "red",
"red", "slow", "the", "turtle"};
biggies(vec, 4);
}
14.41
lambda表达式在作为仅调用一次的可调用对象时非常简便,如果该可调用对象要调用多次,那么使用类更明智
14.42
std::count_if(ivec.cbegin(), ivec.cend(), std::bind(std::greater<int>(), _1, 1024));
std::find_if(svec.cbegin(), svec.cend(), std::bind(std::not_equal_to<std::string>(), _1, "pooh"));
std::transform(ivec.begin(), ivec.end(), ivec.begin(), std::bind(std::multiplies<int>(), _1, 2));
14.43
#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
int main(int argc, char** argv)
{
auto data = { 1,2,3,4,5 };
int input;
cin >> input;
modulus<int> intModulus;
for (auto i : data)
{
if (intModulus(i, input))
cout << input << "不能被" << i << "整除" << endl;
else
cout << input << "能被" << i << "整除" << endl;
}
return 0;
}
14.44
#include <iostream>
#include <map>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
int add(int a, int b)
{
return a + b;
}
class divide{
public:
int operator()(int a, int b)
{
return a / b;
}
};
auto mod = [](int a, int b) {return a % b; };
int Caclate(string op,int a, int b)
{
map < string, function<int(int, int)> >binops;
binops.insert({ "+", add });
binops.insert({ "-",std::minus<int>() });
binops.insert({ "*",[](int a,int b) {return a * b; } });
binops.insert({ "/",divide() });
binops.insert({ "mod",mod });
return binops[op](a, b);
}
int main(int argc, char** argv)
{
string op;
int a, b;
cin >> op >> a >> b;
cout << Caclate(op, a, b);
return 0;
14.45
explicit operator string()const { return bookNo; }
explicit operator double()const { return avg_price(); }
14.46
不应该,explicit应该用来防止隐式转换
14.47
a.编译器会忽略const
b.const成员函数