C++进阶学习---运算符重载

运算符重载

友元

友元函数

友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数

关键字friend
friend 返回值类型 函数名(参数列表);
friend void global_printf(Point const that);	//友元函数
友元类

友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)

//类前面加上friend声明友元类
class Point
{
	int m_x;
	int m_y;
public:
	friend class Point3D;//友元类
};
class Point3D
{
	Point m_p;
	int m_z;
public:
};

注意事项:

  1. 只有友元可以访问,其他依然不能访问。

若类B是类A的友元。则只有类B的成员函数可以访问类A中的隐藏信息

  1. 友元是单向的,不具有交换性。

若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。

  1. 友元关系不具有传递性。

若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明

友元类以及友元函数示例程序
//demo1.cpp
#include<iostream>
using namespace std;
class Point
{
	int m_x;
	int m_y;
public:
	Point(int x = 0, int y = 0);	//缺省构造函数	类内声明类外定义
	void Point_printf();			//类内数据打印函数
	friend void global_printf(Point const that);	//友元函数 类外数据打印函数
	friend class Point3D;			//友元类
};
class Point3D
{
	Point m_p;
	int m_z;
public:
	Point3D(int x = 0, int y = 0, int z = 0);
	void Point3D_printf();
};
int main()
{
	Point point(10,20);
	cout << "========类函数打印========" << endl;
	point.Point_printf();
	cout << "========友元函数打印========" << endl;
	global_printf(point);
	cout << "========友元类打印========" << endl;
	Point3D point3d(10, 20, 30);
	point3d.Point3D_printf();
	cin.get();
	return 0;
}

Point::Point(int x, int y)
{
	m_x = x;
	m_y = y;
}

void Point::Point_printf()
{
	cout << this->m_x << " " << this->m_y << endl;
}

void global_printf(Point const that)
{
	cout << that.m_x << " " << that.m_y << endl;
}

Point3D::Point3D(int x, int y, int z)
{
	m_p.m_x = x;
	m_p.m_y = y;
	m_z = z;
}

void Point3D::Point3D_printf()
{
	cout << m_p.m_x << " " << m_p.m_y << " " << m_z << endl;
}

打印结果:

========类函数打印========
10 20
========友元函数打印========
10 20
========友元类打印========
10 20 30

运算符重载

运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。

重载运算符可以使用成员函数非成员函数(一般是友元函数)两种方法

只能使用其中的一种方法

关键字operator
类名 operator运算符(const 类名& other);//成员函数实现
Complex operator+(const Complex& other);
可重载运算符
双目算术运算符+ (加),-(减),*(乘),/(除),% (取模)
关系运算符==(等于),!= (不等于),< (小于),> (大于>,<=(小于等于),>=(大于等于)
逻辑运算符||(逻辑或),&&(逻辑与),!(逻辑非)
单目运算符+ (正),-(负),*(指针),&(取地址)
自增自减运算符++(自增),–(自减)
位运算符| (按位或),& (按位与),~(按位取反),^(按位异或),,<< (左移),>>(右移)
赋值运算符=, +=, -=, *=, /= , % = , &=, |=, ^=, <<=, >>=
空间申请与释放new, delete, new[ ] , delete[]
其他运算符()(函数调用),->(成员访问),,(逗号),[](下标)
不可重载的运算符
  • .:成员访问运算符
  • .*, ->*:成员指针访问运算符
  • :::域运算符
  • sizeof:长度运算符
  • ?::条件运算符
  • #: 预处理符号
运算符重载注意事项
  1. 运算重载符不可以改变语法结构
  2. 运算重载符不可以改变操作数的个数
  3. 运算重载符不可以改变优先级
  4. 运算重载符不可以改变结合性
  5. 不能创建新的运算符
+,- 运算符重载
Complex operator+(const Complex& other);//+运算符重载	成员函数实现
friend Complex operator-(const Complex&A, const Complex&B);//-运算符重载	非成员函数实现
=赋值运算符重载

如果没有重载赋值运算符,操作系统会有缺省运算符重载,编译器提供的默认拷贝赋值操作符重载,同默认拷贝构造一样,默认拷贝赋值操作符重载同样是浅拷贝。

Complex operator=(const Complex&other);	//=运算符重载	成员函数实现
注意事项
  1. 避免自赋值
  2. 释放旧资源
  3. 分配新资源
  4. 拷贝新内容
  5. 返回自引用
//为了简便,只实现=运算符的避免自赋值,更多请看string类
Complex operator=(const Complex&other)
{
    if (&other != this)	//防止自赋值
	{
		m_real = other.m_real;
		m_imaginary = other.m_imaginary;
	}
	return *this;
}

前++,后++运算符重载
Complex operator++();		//前++运算符重载	成员函数实现
Complex operator++(int);	//后++运算符重载通过哑元实现	成员函数实现

流操作符>>,<<重载

cout是输出类的对象,而cin是输入类的对象,C++头文件iostream取自istream和ostream之意

流操作符>>,<<一般使用非成员函数实现,也就是友元函数实现,这样可以符合程序员的惯性思维

friend ostream &operator<<(ostream &os, const Complex&other);//IO流运算符重载函数一般声明为类的友元函数
friend istream &operator >> (istream &is, Complex&other);		//类的非成员函数重载>>提取运算符

让我们来看一下如果使用类成员方法重载流操作运算符会怎样一个结果

istream &operator>>(istream &is);		//类的成员函数重载>>提取运算符

这样定义的话使用的时候

Complex test;
test >> cin;	//类的成员函数提取运算符的调用

跟自己使用cin不太一样对不对,就像一个反人类的设计…

运算符重载示例程序1

//demo_2.cpp
#include<iostream>
using namespace std;
#define IS_MEMBER 0
class Complex
{
	double m_real;
	double m_imaginary;
public:
	Complex(double r = 0, double i = 0);
	void Complex_show();
	Complex operator+(const Complex& other);					//+运算符重载	成员函数实现
	Complex operator=(const Complex&other);						//=运算符重载	成员函数实现
	Complex operator++();		//前++运算符重载	成员函数实现
	Complex operator++(int);	//后++运算符重载	成员函数实现
	friend Complex operator-(const Complex&A, const Complex&B);	//-运算符重载	非成员函数实现
	friend ostream &operator<<(ostream &os, const Complex&other);//IO流运算符重载函数一般声明为类的友元函数
#if IS_MENBER
	istream &operator>>(istream &is);		//类的成员函数重载>>提取运算符
#else
	friend istream &operator >> (istream &is, Complex&other);		//类的非成员函数重载>>提取运算符
#endif
};
int main()
{
	Complex complex_1(1, 8), complex_2(2, 5), temp;
	cout << "===========+操作符重载===========" << endl;
	temp = complex_1 + complex_2;
	temp.Complex_show();
	cout << "===========流操作符重载===========" << endl;
	Complex test;
#if IS_MENBER
	test >> cin;	//类的成员函数提取运算符的调用
#else
	cin >> test;
#endif
	complex_1 = test;
	cout << "===========-操作符重载===========" << endl;
	temp = complex_1 - complex_2;
	cout <<"temp:"<< temp << endl;
	cout << "============前++后++==========" << endl;
	Complex complex_3(1, 1);
	cout << complex_3++;
	cout << complex_3;
	cout << ++complex_3;


	cin.get();
	cin.get();
	return 0;
}

Complex::Complex(double r, double i)
{
	m_real = r;
	m_imaginary = i;
}

void Complex::Complex_show()
{
	cout << m_real << "+" << m_imaginary << "i" << endl;
}

Complex Complex::operator+(const Complex & other)
{
	Complex temp;
	temp.m_real = this->m_real + other.m_real;
	temp.m_imaginary = this->m_imaginary + other.m_imaginary;
	return temp;
}
Complex Complex::operator=(const Complex & other)
{
	if (&other != this)
	{
		m_real = other.m_real;
		m_imaginary = other.m_imaginary;
	}
	return *this;
}
Complex Complex::operator++()
{
	this->m_real = this->m_real + 1;
	return *this;
}
Complex Complex::operator++(int)
{
	Complex temp = *this;
	this->m_real = this->m_real + 1;

	return temp;
}
#if IS_MENBER
istream & Complex::operator >> (istream & is)
{
	cin >> this->m_real >> this->m_imaginary;
	// TODO: 在此处插入 return 语句
	return is;
}
#else
istream & operator >> (istream & is, Complex & other)
{
	is >> other.m_real >> other.m_imaginary;
	// TODO: 在此处插入 return 语句
	return is;
}

#endif

Complex operator-(const Complex & A, const Complex & B)
{
	Complex temp;
	temp.m_real = A.m_real - B.m_real;
	temp.m_imaginary = A.m_imaginary - B.m_imaginary;
	return temp;
}
ostream & operator<<(ostream & os, const Complex & other)
{
	os << other.m_real << "+" << other.m_imaginary << "i" << " ";
	// TODO: 在此处插入 return 语句
	return os;
}

//运行结果
===========+操作符重载===========
3+13i
===========流操作符重载===========
4 5
===========-操作符重载===========
temp:2+0i
============++++==========
1+1i 2+1i 3+1i

new,delete重载
//类内实现new运算符重载 new的返回值必须是void* 第一个参数必须为size_t
void* operator new(size_t size);//类的非成员函数重载new
//类内实现new运算符重载 new的返回值必须是void* 第一个参数必须为void*
void  operator delete(void* ptr);//类的非成员函数重载delete

注意:对于new的重载返回值必须是void*;delete的重载返回值一定是void

运算符重载示例程序2

//demo_3.cpp
#include<iostream>
using namespace std;
class Integer
{
	char* m_str;
	int m_len;
public:
	Integer()
	{
		m_len = 1;
		m_str = new char[m_len];
		m_str[0] = '\0';
	}
	Integer(const char* str)
	{
		m_len = strlen(str) + 1;	//这个1留给\0
		m_str = new char[m_len];
		strcpy(m_str, str);
	}
	char & operator[](int i);
	//类内实现new运算符重载 new的返回值必须是void* 第一个参数必须为size_t
	void* operator new(size_t size)
	{
		return (Integer*)malloc(size);
	}
	//类内实现new运算符重载 new的返回值必须是void* 第一个参数必须为void*
	void operator delete(void* ptr)
	{
		free(ptr);
	}
	friend ostream &operator<<(ostream &os, const Integer&other);
};

int main()
{
	Integer* arr = new Integer("hello world!");
	cout << *arr << endl;
	Integer str("hello C++!");
	for (int i = 0; i <= 10; i++)
	{
		cout << str[i];
	}
	delete arr;
	cin.get();
	return 0;
}
ostream & operator<<(ostream & os, const Integer & other)
{
	cout << other.m_str;
	// TODO: 在此处插入 return 语句
	return os;
}

char & Integer::operator[](int i)
{
	//TODO: 在此处插入 return 语句
	return m_str[i];
}

//运行结果
hello world!
hello C++!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeRoy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值