C++操作符重载(operator)_#include

为什么使用赋值运算符重载函数?

对于系统的所有操作符,一般情况下,只支持基本数据类型和标准库中提供的class,对于用户自己定义的class或struct的对象,如果想支持基本操作,比如比较大小,判断是否相等,等等,则需要用户自己来定义关于这个操作符的具体实现。

比如,判断两个人是否一样大,我们默认的规则是按照其年龄来比较,所以,在设计person 这个class的时候,我们需要考虑操作符==,而且,根据刚才的分析,比较的依据应该是age。那么为什么叫重载呢?这是因为,在编译器实现的时候,已经为我们提供了这个操作符的基本数据类型实现版本,但是现在他的操作数变成了用户定义的数据类型class,所以,需要用户自己来提供该参数版本的实现


双目操作符重载

赋值类双目操作符重载

成员函数方式

#include <iostream>
//复数类
class Complex{
public:
Complex(int r=0,int i=0):m_r(r),m_i(i){ }
void print(void)const{
std::cout<<m_r<<'+'<<m_i<<'i'<<'\n';
}
//c1+=c2==>c1.operator+=(c2) c1就是自身
Complex& operator+=(const Complex& c ){
m_r+=c.m_r;
m_i+=c.m_i;
return *this;
}

private:
int m_r; //实部
int m_i; //虚部
};

int main()
{
Complex c1(10,20);
Complex c2(5,8);
Complex c3 =c1+=c2;
c3.print();


return 0;
}


全局函数方式

#include <iostream>
//复数类
class Complex {
public:
Complex(int r = 0, int i = 0) :m_r(r), m_i(i) { }
void print(void)const {
std::cout << m_r << '+' << m_i << 'i' << '\n';
}
friend Complex& operator-=(Complex& l, const Complex& r);
private:
int m_r; //实部
int m_i; //虚部
};

//c1-=c2==>operator-=(c1,c2)
Complex& operator-=(Complex& l, const Complex& r) {
l.m_r -= r.m_r;
l.m_i -= r.m_i;
return l;
}


int main()
{
Complex c1(10, 20);
Complex c2(5, 8);
c1 -= c2;
c1.print();


return 0;
}


计算类双目操作符重载

成员函数方式

L#R的表达式可以被编译器处理为“L.operator#(R)”成员函数调用形式,该函数的返回值就是表达式的结果

比如:c1+c2      c1.operator+(c2)

#include <iostream>
//复数类
class Complex{
public:
Complex(int r=0,int i=0):m_r(r),m_i(i){ }
void print(void)const{
std::cout<<m_r<<'+'<<m_i<<'i'<<'\n';
}
//c1+c2==>c1.operator+(c2) c1就是自身
const Complex operator+(const Complex& c) const{ //+操作符重载
//第一个const: 保证返回值是右值
//第二个const:支持常量型右操作数
//第三个const: 支持常量型左操作数
Complex res(m_r+c.m_r,m_i+c.m_i);
return res;
}

private:
int m_r; //实部
int m_i; //虚部
};

int main()
{
Complex c1(10,20);
Complex c2(5,8);
c1.print();
c2.print();
Complex c3=c1+c2;//调用+重载函数
c3.print();



return 0;
}

全局函数方式 

L#R的表达式可以被编译器处理为“operator#(L,R)”全局函数调用形式,该函数的返回值就是表达式的结果 

#include <iostream>
//复数类
class Complex {
public:
Complex(int r = 0, int i = 0) :m_r(r), m_i(i) { }
void print(void)const {
std::cout << m_r << '+' << m_i << 'i' << '\n';
}
friend Complex& operator-=(Complex& l, const Complex& r);
private:
int m_r; //实部
int m_i; //虚部
};

//c1-=c2==>operator-=(c1,c2)
Complex& operator-=(Complex& l, const Complex& r) {
l.m_r -= r.m_r;
l.m_i -= r.m_i;
return l;
}


int main()
{
Complex c1(10, 20);
Complex c2(5, 8);
c1 -= c2;
c1.print();


return 0;
}

单目操作符重载 

计算单目操作符

比如:-(负)   ~(位反)

成员函数实现

#include <iostream>

class Integer {
public:
Integer(int i = 0) :m_i(i) { }
void print(void)const {
std::cout << m_i << std::endl;
}

//Integer j = -i ==>i.operator-()
const Integer operator-(void)const {
//没有形参:操作数就是自身
Integer res(-m_i);
return res;
}

private:
int m_i;
};


// operator

int main()
{
Integer i(100);
Integer j = -i;
j.print();

return 0;
}

全局函数实现

#include <iostream>

class Integer {
public:
Integer(int i = 0) :m_i(i) { }
void print(void)const {
std::cout << m_i << std::endl;
}

//Integer j = -i ==>i.operator-()
friend const Integer operator~(const Integer& i);
private:
int m_i;
};


const Integer operator~(const Integer& i) {
Integer res(i.m_i* i.m_i);
return res;
}

int main()
{
Integer i(100);
Integer j = ~i;
j.print();

return 0;
}

自增减单目操作符

比如:++    --

#include <iostream>

class Integer {
public:
Integer(int i = 0) :m_i(i) { }
void print(void)const {
std::cout << m_i << std::endl;
}

/*
左值:有特定的地址,其值可以修改
a++ 不可以作为左值;++a 可以作为左值
a++的意思是先复制一份临时数据出来参与周边环境的运算,再自加变量a,可见a++用来参与运算的是一份复制出来的临时数据,这个数据是临时存在而没有固定地址的,不是一个真正的变量,所以只能是右值
++a的意思是先自加变量a,再将变量放到周边环境参与运算,那么++a用来参与运算的是有具体地址的变量,所以++a是可以作为左值使用的
哑元:一个函数的参数 只有类型 没有名字 则这个参数称之为哑元
后缀操作符重载会多一个哑元参数,用来与前缀操作符重载的区分
*/

//前++ 成员函数形式
Integer& operator++(void) {
//没有形参:操作数就是自身
++m_i;
return *this;
}
friend Integer& operator--(Integer& i);

//后++ 成员函数形式
const Integer operator++(int) {
//参数:哑元参数
Integer old = *this;
++m_i;
return old;
}

friend const Integer operator--(Integer& i,int);


private:
int m_i;
};

//前-- 全局函数形式
Integer& operator--(Integer& i) {
--i.m_i;
return i;
}

//后-- 全局函数形式
const Integer operator--(Integer& i, int) {
//参数:哑元参数
Integer old = i;
--i.m_i;
return old;
}


int main()
{
Integer i(100);
Integer j=++i;
j.print();

return 0;
}

输入输出操作符重载(<<   >>) 

#include<iostream>

class Complex {
public:
Complex(int r,int i):m_r(r),m_i(i){}

//<< 操作符重载函数
// cout<<c1 ==>operator<<(cout,c1)
friend std::ostream& operator<<(std::ostream& os, const Complex& c) {
os << c.m_r << '+' << c.m_i << 'i';
return os;
}

//>> 操作符重载函数
// cout<<c1 ==>operator>>(cout,c1)
friend std::istream& operator>>(std::istream& is, Complex& c) {
std::cout << "输入实部:";
is >> c.m_r;
std::cout << "输入虚部:";
is >> c.m_i;
return is;
}

private:
int m_r;//实部
int m_i;//虚部
};


int main()
{
Complex c1(10, 20);
Complex c2(1, 2);

std::cout << c1 << std::endl; //"10+20i"
std::cin >> c2;
std::cout << c2 << std::endl;

return 0;
}

可见,当用一个非类A的值(如上面的int型值)为类A的对象赋值时:

①如果匹配的构造函数和赋值运算符重载函数同时存在,会调用赋值运算符重载函数

②如果只有匹配的构造函数存在,就会调用这个构造函数


重载运算符的规则:

C++操作符重载(operator)_操作符_02


重载运算符的函数不能有默认的参数:不然就改变了运算符参数的个数

重载运算符的函数参数至少有一个是本类的对象或引用,不能全部都是C++的基本类型