c++面向对象运算符重载

运算符重载

运算符重载的含义:运算符重载,就是对已有的运算符(C++中预定义的运算符)赋予多
重的含义,使同一运算符作用于不同类型的数据时导致不同类型的行为。
目的:扩展C++中提供的运算符的适用范围,使之能作用于对象
运算符重载的形式

  1. 运算符重载的实质是函数重载
  2. 可以重载为普通函数,也可以重载为成员函数
  3. 把含运算符的表达式转换成对运算符函数的调用
  4. 把运算符的操作数转换成运算符函数的参数
  5. 运算符被多次重载时,根据实参的类型决定调用哪一个运算符
    模板
返回值类型 operator 运算符 (形参表){
		.....
}

示例:

class Compelx{
	public:
		double real, imag;
		Complex(double r=0.0, double i=0.0):real(r),imag(i){ }
		Complex operator-(const Complex & c);
};
Complex operator + (const Complex &a, const Compelx &b){
	return Complex(a.real+b.real, a.imag+b.imag);
Complex Complex::operator-(const Complex & c){
	return Complex(real - c.real, iamg - c.imag);
}
int main(){
	Complex a(4,4), b(1,1), c;
	c = a+b; //等价于c=operator+(a,b);
	cout << c.real << "," << c.imag << endl;
	cout << (a-b).real << "," << (a-b).imag << endl;  // a-b等价于a.operator-(b)
	return 0;
}
输出
55
33

可以看出:

  1. 重载为成员函数,参数个数为运算符目数减一
  2. 重载为普通函数时,参数个数为运算符目数
赋值运算符的重载

先看一个例子

class String{
	private;
		char *str;
	public:
		String (): str(new char[1]) { str[0] = 0;}
		const char *c_str() { return str; };
		String & operator = (const char * s);
		String::~Stirng() {delete []str;}
}
String & String::operator = (coonst char * s){
	delete [] str;
	str = new char[strlen(s)+1];
	strcpy(str, s);
	return *this;
}
int main(){
	String s;
	s = "Good Luck,"; // 等价于 s.operator = ("Good Luck,")
	cout << s.c_str() << endl;
	return 0;
}

深拷贝和浅拷贝

class String{
	private:
		char *str;
	public:
		String () : str(new char[1]) { str[0] = 0;}
		const char * c_str() { return str;} ;
		String &operator = (const char *s){
			delete [] str;
			str = new char[strlen(s)+1];
			strcpy(str s);
			return *this;
		}
		~String () { delete [] str}
}
int main(){
	String s1, s2;
	s1 = "this";
	s2 = "that";
	s1 = s2;
}

在这里插入图片描述

  1. 如果不定义自己的赋值运算符上述代码就会导致是s1.str和s2.str指向同一个地方
  2. 另外,如果s1对象消亡,析构函数将释放s1.str指向的空间, 则s2消亡的时候还要释放一次,butuo
  3. 另外,s1 = “other” 会导致 s2.str()指向的地方被delete
  4. 因此需要在class String添加成员函数
String & operator = (const String & s){
	delete [] str;
	str = new char[strlen(s.str) + 1];
	strcpy (str, s.str);
	return *this;
}

考虑下面的语句

String s;
s = "Hello";
s = s;

会先把自己的内存空间释放掉再给自己赋值,因而出现错误
解决办法

String & operator = (const String & s){
	if(this == &s){
		return *this;
	}
	delete [] str;
	str = new char[strlen(s.str) + 1];
	strcpy (str, s.str);
	return *this;
}

对operator = 返回值的讨论
void
a = b = c; // 等价于 a.operator = ( b.operator©);
String
(a=b)=c; // (a.operator = (b)).operator©;
另外定义=的赋值构造函数的时候也需要进行相同的处理

运算符重载为友元函数

一般情况下,将运算符重载为类的成员函数,是比较好的选择
但有时,重载为成员函数不能满足要求,重载为普通函数又不能访问私有成员,所以需要将运算符重载为友元

class Complex{
	double real, imag;
	public:
		Complex(doulble r, double i): real(r), imag(i){ };
		Complex operator+(double r);
};
Complex Complex::operator+(double r){ // 能解释c+5
	return Complex(real+r, imag);
}
// 所以需要定义普通成员函数
Complex operator+double r, const Complex &c){  // 能解释5+c
	return Complex(c.real+r, c.imag);
}
// 因为需要访问私有成员,所以需要把Complex operator+ (double r, const Complex &c)写成友元函数
运算符重载实例 — 可变长数组
class CArray{
	int size;
	int *ptr;
	public:
		CArray(int s=0);
		CArray(CArray &a);
		~CArray();
		void push_back(int v);
		CArray &operator = (const CArray &a);
		int length() { return size;}
		int & CArray::operator[](int i){
			return ptr[i];
		}
};
CArray::CArrray(int s): size(s){
	if(s == 0) ptr = NULL;
	else ptr = new int[s];
}
CArray::CArray(CArray & a){
	if(!a.ptr){
		ptr = NULL;
		size = 0;
		return ;
	}
	ptr = new int[a.size];
	memcpy(ptr, a.ptr, sizeof(int)*a.size);
	size = a.size;
}
CArray::~CArray(){
	if(ptr) delete [] ptr;
}
CArray & CArray::operator=(const CArray &a){
	if(ptr == a.ptr) return *this;
	if(a.ptr == NULL){
		if(ptr) delete []ptr;
		ptr = NULL;
		size = 0;
		return *this;
	}
	if(size < a.size){
		if(ptr)
		delete []ptr;
		ptr = new int[a.size()];
	}
	memcpy (ptr, a.ptr, sizeof(int)*a.size());
	size = a.szie();
	return *this;
}
void CArray::push_back(int v){
	if(ptr){
		int * tmpPtr = new int[size+1];
		memcpy(tmpPtr, ptr, sizeof(int)*size);
		delete []ptr;
		ptr = tmpPtr;
	}
	else ptr = new int[1];
	ptr[size++] = v;
}
int main(){
	CArray a;
	for(int i=0; i<5; i++){
		a.push_back(i);
	}
	CArray a2, a3;
	a2 = a;
	for(int i=0;i<a.length();i++)   cout << a2[i] << " ";
	cout << endl;
	a[3] = 100;
	CArray a4(4);
	for(int i=0; i<a4.lenght(); i++) cout << a4[i] << " ";
	return 0;
}
流插入运算符和流提取运算符的重载

cout << iostream 中定义的, ostream类的对象
“<<” 能用在 cout 上是因为, 在iostream 里对 “<<” 进行了重载

ostream & ostream::operator<<(itn n){
	......//输出n的代码
	return *this;
}
ostream & ostream::operator<<(const char *s){
	.....//输出s的代码
	return *this;
}

示例:对复数的输出

#include<bits/stdc++.h>
#include<string>
#include<cstdlib>
using namespace std;
class Complex {
	double real, imag;
	public:
		Complex(double r=0, double i=0):real(r), imag(i){};
		friend ostream & operator<<(ostream & os, const Complex & c);
		friend istream & operator>>(istream & is , Complex &c);
}
ostream & operator << (ostream & os, const Complex & c){
	os << c.real << "+" << c.imag << "i";
	return os;
}
istream & operator>>(istraem & is, Complex &c){
	string s;
	is >> s;
	int pos = s.find("+", 0);
	string sTmp = s.substr(0, pos);
	c.real = atof(sTmp.c_str());
	sTmp = s.substr(po+1, s.length()-pos-2);
	c.imag = atof(sTmp.c_str());
	return is;
}
int main(){
	Complex c;
	int n;
	cin >> c >> n;
	cout << c << "," << n;
	return 0;
}
重载类型转换运算符
#include<iostream>
using namespace std;
class Complex{
	double real, imag;
	public:
		Complex(double r=0, double i=0): real(r), imag(i) { };
		operator double () { return real;} // 重载强制类型转换运算符 double 
};
int main(){
	Complex c(1.2, 3.4);
	cout << (double)c << endl;  // 输出1.2
	double n = 2+c;   // 等价于 double n = 2 + c.operator()
	cout << n;           // 输出3.2
}
自增自减运算符重载

前置运算符重载为一元运算符
重载为成员函数
T & operator++();
T & operator–();
重载为全局函数
T1 & operator++(T2);
T2 & operator–(T2);
后置运算符重载为二元运算符,多写一个没用的参数
重载为成员函数
T operator++(int );
T operator–(int );
重载为全局函数
T1 operator(T2, int);
T1 operator(T2, int);
示例

class CDemmo{
	private:
		int n;
	public:
		CDemo (int i = 0):n(i) { }
		CDemo & operator++();
		CDemo operator++ (int );
		operator int ( ) { return n;}
		friend CDemo & operator--(CDemo & );
		friend CDemo operator--( CDemo &, int ); 
};
CDemo & CDemo::operator++(){
	n ++;
	return * this;
}
CDemo CDemo::operator++( int k){
	CDemo tmp (* this);
	n ++;
	return tmp;
}
CDemo & operator--(CDemo & d){
	d.n--;
	return d;
}
CDemo operator--(CDemo & d, int){
	CDemo tmp(d);
	d.n --;
	return tmp;
}
operator int ( ){ return n; }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值