class ClassName { friend ostream& operator<<(ostream&, ClassName&); friend istream& operator>>(istream&, ClassName&); private: string name; }; ostream& operator<<(ostream& os, ClassName& obj) { os << obj.name; return os; } istream& operator>>(istream& is, ClassName& obj) { is >> obj.name; //处理输入错误 //设置foilbit、eofbit、badbit return is; }
Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs) { Sales_data sum = lhs; // copy data members from lhs into sum sum += rhs; // add rhs into sum return sum; } bool operator==(cons tSales_data &lhs, const Sales_data &rhs) { return lhs.isbn() == rhs.isbn() && lhs.units_sold == rhs.units_sold && lhs.revenue == rhs.revenue; } bool operator!=(const Sales_data &lhs, const Sales_data &rhs) { return!(lhs == rhs); }
在拷贝控制中讲解了赋值运算符的拷贝赋值和移动赋值,还有一种是使用花括号列表进行赋值。
vector<string> vec; vec = { "123" ,"456","789" };
对于之前编写的动态内存管理类,我们可以添加这个赋值特性
//列表赋值运算符 StrVec &operator= (std::initializer_list<std::string> ls) { auto data = alloc_n_copy(ls.begin(), ls.end()); free(); elements = data.first; first_free = cap = data.second; return *this; }
下标运算符通常定义两个版本,一个是const版本,另一个是nonconst版本。
下标运算符必须是成员函数。
//下标运算符 std::string&operator[](std::size_t n) { return elements[n]; } const std::string& operator[](std::size_t n) const { return elements[n]; }
There are both prefix and postfix versions. These operators usually should be defined as members.
class StrBlobPtr { public: // increment and decrement StrBlobPtr&operator++(); // prefix operators StrBlobPtr&operator--(); StrBlobPtr operator++(int); // postfix operators StrBlobPtr operator--(int); // other members as before }; // prefix:return a reference to the incremented/decremented object StrBlobPtr& StrBlobPtr::operator++() { // if curr already points past the end of the container, can‘t increment it check(curr, "increment past end of StrBlobPtr"); ++curr; // advance the current state return*this; } StrBlobPtr& StrBlobPtr::operator--() { // if curr is zero, decrementing it will yield an invalid subscript --curr; // move the current state back one element check(-1, "decrement past begin of StrBlobPtr"); return*this; } // postfix: increment/decrementthe object but return the unchanged value StrBlobPtr StrBlobPtr::operator++(int) { // no check needed here; the call to prefix increment will do the check StrBlobPtrret = *this; // save the current value ++*this; // advance one element; prefix ++ checks the increment returnret; // return the saved state } StrBlobPtr StrBlobPtr::operator--(int) { // no check needed here; the call to prefix decrement will do the check StrBlobPtrret = *this; // save the current value --*this; // movebackward one element; prefix -- checks the decrement returnret; // return the saved state }
在迭代器类以及智能指针类中,拥有成员访问运算符,包括解引用运算符、箭头运算符。
对于内置的指针类型,访问其成员我们使用(*ptr).mem,使用ptr->men与之等价,“ptr->”实际上就成为了“(*ptr).”。
对于定义了->运算符的对象,我们使用*和->都将使用自定义的版本。
class Ptr { std::string& operator*() const { auto p = check(curr, "dereference past end"); return(*p)[curr]; // (*p) is the vector to which this object points } std::string*operator->() const {// delegate the real work to the dereference operator return&this->operator*(); } };
Objects of classes that define the call operator are referred to as function objects. Such objects “act like functions” because we can call them.
class absInt { public: int operator()(int integer) { return integer > 0 ? integer : -integer; } }; int main() { absInt funObj; int b = funObj(-155); }
lambda表达式实际上就是一个函数对象,捕获列表中的数据将会成为对象的成员。
Arithmetic算术
plus<Type> |
minus<Type> |
multiplies<Type> |
divides<Type> |
modulus<Type> |
negate<Type> |
Relational关系
equal_to<Type> |
note_equal_to<Type> |
greater<Type> |
greater_equal<Type> |
less<Type> |
less_equal<Type> |
Logical逻辑
logical_amd<Type> |
logical_or<Type> |
logical_not<Type> |
默认情况下sort使用<进行排序,为降序。可以如下使用升序。
#include<functional> sort(svec.begin(), svec.end(), greater<string>());
调用形式(call signature):int(int,int)
不同的类型,具有相同的调用形式
//普通函数 int add(int i, int j) { return i + j; } //lambda,其产生一个未命名的函数对象类 auto add = [](int i, int j) { return i + j; }; //函数对象类 class add { int operator()(int i, int j) { return i + j; } };
这种调用形式,可以用一种模板类型代替
#include<functional> function<int(int, int)> fun;
function不能识别重载函数
//普通函数 int add(int i, int j) { return i + j; } double add(int i, double j) { return i + j; } //这句话会出错 function<int(int, int)> fun = add;
函数指针可以识别重载
//函数指针可以识别重载 int(*f)(int, int) = add; function<int(int, int)> fun = f;
转换构造函数(将其他类型转换成自己)
构造函数只接受一个实参,实际上定义了此类型的隐式转换机制。当然,可以使用explicit声明阻止这个转换。
隐式类型转换运算符(将自己转换成其他类型)
operator type() const;
class SmallInt { public: operator int()const { return val; } private: std::size_t val; };
显式类型转换运算符(将自己转换成其他类型)
explicit operator type() const;
如果表达式用在条件语句,则会隐式执行
class SmallInt { public: explicit operator int()const { return val; } private: std::size_t val; } int main() { SmallInt si; int a = static_cast<int>(si); }
转换为bool
while(std::cin>>value)
cin的>>运算符返回cin本身,因为在条件语句,隐式转换成bool类型。
非条件语句中,如cin<<2,因为cin没有定义<<、如果cin可以隐式转换成bool,则可以将<<用作左移符号。但是非条件语句,不能隐式转换,所以这句话是错误的。
The easiest rule of all: With the exception of an explicitconversion to bool, avoid defining conversion functions and limit nonexplicit constructors to those that are “obviously right.”
当我们使用内置类型与类类型进行运算的时候,若有运算符重载和类定义的类型转换,则可能会发生二义性。
A定义了参数为int的转换构造函数和转换为int的类型转换函数,并且有重载的运算符+,则A的对象a进行运算a+10就会产生二义性,无法确定是对a转换成int进行的内置加法,还是10转换成A的重载加法。
原文:http://www.cnblogs.com/qiusuo/p/5106024.html