运算符重载(C++)

  • 五、运算符重载
    • 5.1 什么是运算符重载
    • 5.2 双目运算符重载
    • 5.3 单目运算符重载
      • 5.3.1 计算类单目运算符
      • 5.3.2 前缀自增减单目运算符
      • 5.3.3 后缀自增减单目运算符
    • 5.4 其他运算符重载
      • 5.4.1 输入输出运算符重载
      • 5.4.2 new和delete运算符重载
    • 5.5 编程综合实例

五、运算符重载

5.1 什么是运算符重载

#include 
using namespace std;

class Complex{
private:
	double x;
	double y;
public:
	Complex(double x, double y){
		this->x = x;
		this->y = y;
	}
	void print() {
		cout << x << " + " << y << endl;
	}
};
int main(void) {

	Complex c1(3,6);
	Complex c2(8,3);

	c1.print();
	c2.print();

	int x = 10;
	int y = 20;
	int z = x + y;

	c1 + c2; //想实现和 'int z = x + y;' 一样的功能,这时就要用到运算符重载了

	return 0;
}

5.2 双目运算符重载

**双目运算符:**有左右两个操作数的操作符 L#R

  • 算术运算:*、/、%、+、-
  • 关系运算:>、>=、<、<=、==、!=
  • 逻辑运算:&&、||
  • 位运算:&、|、^、<<、>>
  • 赋值与复合赋值:+=、=、-+、*=、/=、%=、&=、|=、^=、<<=、>>=
  • ……

注意:

  • 表达式结果是右值
  • 左右操作数既可以是左值也可以是右值

实现方式:

  • 成员函数形式:L.operator#®
  • 友元函数形式:operator#(L,R)
#include 
using namespace std;

class Complex{
private:
	double x;
	double y;
public:
	Complex(double x, double y){
		this->x = x;
		this->y = y;
	}
	void print() {
		cout << x << " + " << y << endl;
	}
	const Complex operator+ (const Complex& c){ //成员函数形式
		Complex temp(x+c.x, y+c.y);
		return temp;
	}
	friend const Complex operator*(const Complex& l, const Complex& r);//友元函数形式
	friend const Complex operator/(const Complex& l, const Complex& r);
};

const Complex operator*(const Complex& l, const Complex& r){
	Complex temp(l.x * r.x, l.y * l.x);
	return temp;
}

const Complex operator/(const Complex& l, const Complex& r){
	Complex temp(l.x / r.x, l.y / l.x);
	return temp;
}

int main(void) {

	Complex c1(3,6);
	Complex c2(8,3);

	Complex c3 = c1+c2; //c1.operator+(c2)
	c3.print();

	Complex c4 = c1*c2; //operator*(c1, c2)
	c4.print();

	Complex c5 = c1/c2;
	c5.print();

	return 0;
}

对赋值类双目运算符重载时需要注意的事项:

  • 表达式的结果是左值,就是左操作数的自身
  • 左操作数必须是左值,右操作数可以是左值也可以是右值
#include 
using namespace std;

class Complex{
private:
	double x;
	double y;
public:
	Complex(double x, double y){
		this->x = x;
		this->y = y;
	}
	void print() {
		cout << x << " + " << y << endl;
	}

	Complex operator+=(Complex& c){//成员函数形式
		x += c.x;
		y += c.y;
		return *this;
	}
   //						左操作数		右操作数
	friend Complex operator-=(Complex& l, const Complex& r);//友元函数形式
};

Complex operator-=(Complex& l, const Complex& r){
	l.x -= r.x;
	l.y -= r.y;
	return l;
}
int main(void) {

	Complex c1(3,6);
	Complex c2(8,3);

	c1 += c2; //operator+=(&c1,c2)
	c1.print();

	(c1 -= c2).print();
	return 0;
}

5.3 单目运算符重载

**单目运算符:**只有一个操作数的运算符 #O

  • 相反数:-
  • 位反:~
  • 逻辑非:!
  • 自增:++
  • 自减:–
  • ……

5.3.1 计算类单目运算符

注意:

  • 表达式结果是右值
  • 操作数可以是左值也可以是右值

实现方式:

  • 成员函数形式:O.operator#();
  • 友元函数形式:operator#(O);
#include 
using namespace std;

class Integer{
private:
	int i;
public:
	Integer(int i){
		this->i = i;
	}
	void print() {
		cout << "i = " << i << endl;
	}
	/*
	const Integer operator-(){ //成员函数形式
		return Integer(-i);
	}
	*/
	friend const Integer operator-(const Integer& i); //友元函数形式
};

const Integer operator-(const Integer& i){

	return Integer(-i.i);
}
int main(void) {
	
	Integer a = 100;
	Integer b = -a;

	b.print();

	return 0;
}

5.3.2 前缀自增减单目运算符

注意:

  • 表达式结果是左值
  • 操作数必须是左值

实现方式:

  • 成员函数形式:O.operator#();
  • 友元函数形式:operator#();
#include 
using namespace std;

class Integer{
private:
	int i;
public:
	Integer(int i){
		this->i = i;
	}
	void print() {
		cout << "i = " << i << endl;
	}
	Integer& operator++(){ //成员函数形式
		++i;
		return *this;
	}
	friend Integer& operator--(Integer& i); //友元函数形式
};

Integer& operator--(Integer& i){
	--i.i;
	return i;
}

int main(void) {
	
	Integer a = 100;
	++(++a);
	(--(--a)).print();

	a.print();	
	return 0;
}

5.3.3 后缀自增减单目运算符

注意:

  • 表达式结果是右值,是操作数自增减前的版本
  • 操作数必须是左值

实现方式:

  • 成员函数:O.operator#(哑元);
  • 友元函数:operator#(O, 哑元);
#include 
using namespace std;

class Integer{
private:
	int i;
public:
	Integer(int i){
		this->i = i;
	}
	void print() {
		cout << "i = " << i << endl;
	}
	Integer& operator++(){
		++i;
		return *this;
	}
	Integer& operator--(){
		--i;
		return *this;
	}
	const Integer operator++(int){
		Integer old = *this;
		++(*this); //++(this->i)

		return old;
	}
	friend const Integer operator--(Integer& o, int);
};

const Integer operator--(Integer& o, int){
	Integer old = o.i; // o
	--o.i; // o

	return old;
}
int main(void) {
	
	Integer a = 100;
	
	Integer b = a++;
	b.print();
	a.print();

	Integer c = a--;
	c.print();
	a.print();
	return 0;
}

5.4 其他运算符重载

5.4.1 输入输出运算符重载

friend ostream& operator<<(ostream& os, const RIGHT& right){...}
	ostream, 标准库类
    cout << a ; //operator<<(cout, a)
friend ostream& operator>>(istream& is, const RIGHT& right){...}
	ostream cin; //istream标准库类
    cin << a ; //operator>>(cin, a)

注:因为无法向标准库类添加成员函数,所以只能使用全局函数的形式

#include 
using namespace std;

class Complex{
private:
	double x;
	double y;
public:
	Complex(double x, double y){
		this->x = x;
		this->y = y;
	}
	friend ostream& operator<<(ostream& os, Complex& c);
	friend istream& operator>>(istream& is, Complex& c);
};

ostream& operator<<(ostream& os, Complex& c){
	os << c.x << " + " << c.y;
	return os;
}

istream& operator>>(istream& is, Complex& c){
	is >> c.x >> c.y;
	return is;
}

int main(void) {

	Complex c1(3,6);

	cout << c1 << endl;

	Complex c2(0,0);
	
	cin >> c2;
	cout << c2 << endl;
	return 0;
}

5.4.2 new和delete运算符重载

通过new创建该类的对象时,将首先调用该操作符函数分配内存(可重载),然后再调用该类的构造函数

通过delete销毁该类的对象时,将首先调用该类的析构函数,然后再调用操作符函数释放内存(可重载)

#include 
#include 
using namespace std;

class A{
public:
	A(void){
		cout << "A (void) " << endl;
	}
	~A(void){
		cout << "~A (void) " << endl;
	}
	void* operator new(size_t size){
		cout << "A new" << endl;
		return malloc(size);
	}
	void operator delete(void *p){
		cout << "A delete" << endl;
		free(p);
	}
};
int main(void){

	A *p = new A;

	delete p;

	return 0;
}
//输出结果
myubuntu@ubuntu:~/lv19/cplusplus/dy06$ ./a.out 
A new
A (void) 
~A (void) 
A delete

5.5 编程综合实例

实现一个 3*3 的矩阵类,支持如下操作符:

  • 运算类双目运算符:+ - *
  • 赋值类双目操作符:+= -+ *=
  • 单目操作符:-(相反数)
  • 输出操作符:<<
#include 
using namespace std;

class Mat33{
private:
	int m_a[3][3];
public:
	Mat33(void){
		for(int i=0; i<3; i++){
			for(int j=0; j<3; j++){
				m_a[i][j] = 0;
			}
		}
	}
	Mat33(int a[][3]){
		for(int i=0; i<3; i++){
			for(int j=0; j<3; j++){
				m_a[i][j] = a[i][j];
			}
		}
	}

	const Mat33 operator+(const Mat33& m){ // +   a+b
		int a[3][3] = {0};
		for(int i=0; i<3; i++){
			for(int j=0; j<3; j++){
				a[i][j] = m_a[i][j] + m.m_a[i][j];
			}
		}
		Mat33 result(a); //创建临时对象  调用Mat33类中的 有参构造函数
		return result;
	}

	const Mat33 operator-(const Mat33& m){ // -   a-b
		int a[3][3] = {0};
		for(int i=0; i<3; i++){
			for(int j=0; j<3; j++){
				a[i][j] = m_a[i][j] - m.m_a[i][j];
			}
		}
		Mat33 result(a); //创建临时对象  调用Mat33类中的 有参构造函数
		return result;
	}

	const Mat33 operator*(const Mat33& m){ // *   a*b
		int a[3][3] = {0};
		for(int i=0; i<3; i++){
			for(int j=0; j<3; j++){
				for(int k=0; k<3; k++){
					a[i][j] += m_a[i][k] * m.m_a[k][j];
				}
			}
		}
		Mat33 result(a); //创建临时对象  调用Mat33类中的 有参构造函数
		return result;
	}

	Mat33& operator+=(const Mat33& m){ // +=   a+=b
		*this = *this + m;
		return *this;
	}
	
	Mat33& operator-=(const Mat33& m){ // -=   a-=b
		*this = *this - m;
		return *this;
	}
	Mat33& operator*=(Mat33& m){ // *=   a*=b
		*this = *this * m;
		return *this;
	}

	const Mat33 operator-(void){
		Mat33 m;
		return (m - *this); // operator-(m)
	}

	friend ostream& operator<<(ostream& os, Mat33& m);
};

ostream& operator<<(ostream& os, Mat33& m){
	for(int i=0; i<3; i++){
			os << "\t" ;
		for(int j=0; j<3; j++){
			os << m.m_a[i][j] << " ";
		}
		cout << endl;
	}
	return os;
}
int main(void) {
	int arr1[3][3] = {1,2,3,4,5,6,7,8,9};
	int arr2[3][3] = {9,8,7,6,5,4,3,2,1};

	Mat33 m1(arr1);
	Mat33 m2(arr2);

	cout << " m1 : \n" << m1 << endl;
	cout << " m2 : \n" << m2 << endl;
	
	Mat33 m3 = m1 + m2;
	cout << "m1 + m2 : \n" << m3  << endl;

	Mat33 m4 = m1 - m2;
	cout << "m1 - m2 : \n" << m4  << endl;

	Mat33 m5 = m1 * m2;
	cout << "m1 * m2 : \n" << m5  << endl;

	m1 += m2;
	cout << "m1 += m2 : \n" << m1  << endl;

	m1 -= m2;
	cout << "m1 -= m2 : \n" << m1  << endl;

	m1 *= m2;
	cout << "m1 *= m2 : \n" << m1  << endl;

	Mat33 m6 = -m2;
	cout << " -m2 : \n" << m6  << endl;

	return 0;
}

注意:不是所有的操作符都能重载,下面操作符不能重载

::	.	?:	sizeof	typeid

你可能感兴趣的:(c++,开发语言)