若运算符是成员函数,左侧运算对象绑定到隐式的this指针上,所以成员运算符函数的(显式)参数数量比运算符的运算对象少一个。
选择是否作为成员函数:
1. 必须成员:赋值= 下标[] 调用() 访问->
2. 复合赋值一般应该成员
3. 改变对象状态或与类型紧密相关的,一般应该成员,如 ++ -- 解引用*
4. 对称性运算符可能转换任意一端对象,一般非成员。
1. 输入输出运算符
class Point {
// 以与原点之间距离排序
public:
Point(int x = 0, int y = 0) :m_ix(x),m_iy(y) {}
friend std::ostream& operator<<(std::ostream& os, const Point& point);
friend std::istream& operator>>(std::istream& is, Point& point);
private:
int m_ix;
int m_iy;
};
/* 输出运算符
* 形参1:非常量 ostream 引用;形参2:常量引用(欲打印类型)
* 返回 ostream 形参
*/
std::ostream& operator<<(std::ostream& os, const Point& point) {
//os << "(" << point.getX() << "," << point.getY() << ")";
os << "(" << point.m_ix << "," << point.m_iy << ")";
return os;
}
/*
* 输入运算符必须处理可能的输入失败的情况
*/
std::istream& operator>>(std::istream& is, Point& point) {
is >> point.m_ix >> point.m_iy;
if (!is) {
point.m_ix = -1;
point.m_iy = -1;
}
return is;
}
int main()
{
Point A(1, 2), B(2, 3);
std::cout << A << B << std::endl;
Point C(0,0);
std::cin >> C;
std::cout << C << std::endl;
return 0;
}
2. (复合)赋值运算符
class Point {
// 以与原点之间距离排序
public:
Point(int x = 0, int y = 0) :m_ix(x),m_iy(y) {}
//赋值运算符
Point& operator=(const Point& point);
//复合赋值运算符
Point& operator+=(const Point& point);
Point& operator-=(const Point& point);
private:
int m_ix;
int m_iy;
};
Point& Point::operator=(const Point& point) {
m_ix = point.m_ix;
m_iy = point.m_iy;
return *this;
}
Point& Point::operator+=(const Point& point) {
m_ix += point.m_ix;
m_iy += point.m_iy;
return *this;
}
Point& Point::operator-=(const Point& point) {
m_ix -= point.m_ix;
m_iy -= point.m_iy;
return *this;
}
int main()
{
return 0;
}
3. 前置/后置 递增递减运算符
class Point {
// 以与原点之间距离排序
public:
Point(int x = 0, int y = 0) :m_ix(x),m_iy(y) {}
Point& operator++();
Point& operator--();
Point operator++(int); // 后置
Point operator--(int);
private:
int m_ix;
int m_iy;
};
Point& Point::operator++() {
++m_ix;
++m_iy;
return *this;
}
Point& Point::operator--() {
--m_ix;
--m_iy;
return *this;
}
Point Point::operator++(int)
{
Point tmp = *this;
++* this;
return tmp;
}
Point Point::operator--(int)
{
Point tmp = *this;
--* this;
return tmp;
}
int main()
{
Point A(1, 2);
std::cout << A << std::endl;//1,2
++A;
std::cout << A << std::endl;//2,3
--A;
std::cout << A << std::endl;//1,2
std::cout << A++ << std::endl;//2,3 -> 1,2
std::cout << A-- << std::endl;//1,2 -> 2,3
return 0;
}
4. 算术运算符
Point operator+(const Point& lhs, const Point& rhs) {
Point ptemp = lhs;
ptemp += rhs;
return ptemp;
}
int main()
{
Point A(0,0),B(1,2),C(2,3);
A = B + C;
return 0;
}
5. 关系运算符
class Point {
// 以与原点之间距离排序
public:
Point(int x = 0, int y = 0) :m_ix(x),m_iy(y) {}
int getX()const { return m_ix; }
int getY()const { return m_iy; }
int distance()const {
return m_ix * m_ix + m_iy * m_iy;
}
bool operator<(const Point& point);
private:
int m_ix;
int m_iy;
};
bool operator==(const Point& lhs, const Point& rhs) {
return lhs.getX() == rhs.getX()
&& lhs.getY() == rhs.getY();
}
bool operator!=(const Point& lhs, const Point& rhs) {
return !(lhs == rhs);
}
bool Point::operator<(const Point& point) {
if (distance() < point.distance()) {
return true;
}
return false;
}
6. 函数调用运算符
普通函数的无状态特点。
重载了函数调用运算符,该类 对象 可作为一个函数使用。即函数对象。
操作数个数是不固定的。
返回类型 类名::operator()(参数列表)
{
// ...
}
#include <iostream>
class FunctionClass
{
public:
FunctionClass(int icalls = 0) :m_iCall(icalls) {}
void operator()(int x) {
++m_iCall;
std::cout << "(" << x << ")" << std::endl;
std::cout << m_iCall << " calls" << std::endl;
}
void operator()(int x,int y) {
++m_iCall;
std::cout << "(" << x << "," << y << ")" << std::endl;
std::cout << m_iCall << " calls" << std::endl;
}
private:
int m_iCall;
};
int main()
{
FunctionClass fo;
fo(1);
fo(1, 2);
return 0;
}
7. 下标访问运算符
arr[idx] 解释为 arr.operator[](idx)
返回类型 &类名::operator[](参数类型);
返回类型 &类名::operator[](参数类型) const;
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h>
class mystr
{
public:
mystr(std::size_t size = 10)
: m_iSize(size)
, m_pChar(new char[m_iSize]())
{
}
friend std::ostream& operator<<(std::ostream& os, const mystr& str);
mystr& operator=(const std::string& str) {
std::cout << "mystr& operator=" << std::endl;
m_iSize = str.size() + 1;
delete[] m_pChar;
m_pChar = new char[m_iSize]();
strcpy(m_pChar, str.c_str());
return *this;
}
char& operator[](std::size_t idx)
{
if (idx < m_iSize)
{
return m_pChar[idx];
}
else
{
static char nullchar = '\0';
return nullchar;
}
}
const char& operator[](std::size_t idx) const//针对的是const对象
{
if (idx < m_iSize)
{
return m_pChar[idx];
}
else
{
static char nullchar = '\0';
return nullchar;
}
}
~mystr()
{
delete[] m_pChar;
m_pChar = nullptr;
}
private:
std::size_t m_iSize;
char* m_pChar;
};
std::ostream& operator<<(std::ostream& os, const mystr& str)
{
os << str.m_iSize << "long; " << str.m_pChar;
return os;
}
int main()
{
const std::string str("hello");
mystr obj;
obj = str;
std::cout << obj << std::endl;
std::cout << "obj[1]: " << obj[1] << std::endl;
return 0;
}