运算符的重载
[TOC]
一、重载是否作为类员
- 有些运算符只能作为类成员来重载,这种情况下,和定义类成员函数区别不大,比如说=、[]、调用()、和成员访问箭头->
- 有些运算符,最好作为类的友元来重载,例如算数操作符、相等操作符,关系操作符等;
二、输入输出运算符
它们只能定义为普通的非成员函数,注意函数的参数例如
// 调用本类输出操作符重载
friend ostream &operator<<(ostream &out, const OverloadClass &overloadObj);
// 调用本类输入操作重载
friend istream &operator>>(istream &in, OverloadClass &overloadObj);
三、+号运算符
最好定义为非成员函数
四、+=运算符
既可以定义为成员函数,也可以定义为非成员函数,但是不能同时使用
//====================事实正面这两个都可以使用,但是不能同时使用
// += 操作符重载,类成员函数,需要一个变量
//OverloadClass operator+=(const OverloadClass &overLoad);
// += 操作符重载,非类成员函数,
friend OverloadClass &operator+=(OverloadClass &objLeft, const OverloadClass &objRight);
//
//OverloadClass OverloadClass::operator+=(const OverloadClass& overLoad)
//{
// this->productName += overLoad.productName;
// this->productQuantiy += overLoad.productQuantiy;
// this->productPrice += overLoad.productPrice;
// return *this;
//}
// += 操作符重载,非类成员函数,
OverloadClass &operator+=(OverloadClass &objLeft, const OverloadClass &objRight)
{
objLeft.productName += objRight.productName;
objLeft.productQuantiy += objRight.productQuantiy;
objLeft.productPrice += objRight.productPrice;
return objLeft;
}
五、==运算符
即可定义为类成员函数、也可定义为非类成员函数,并且两种定义可以同时存在,两种定义都存在时
//=====================注意以下两种方法都可以使用,下面看看两个都存在使用哪个?两个都存在时优先选用类成员函数
// == 操作符重载
friend bool operator==(const OverloadClass &objLeft, const OverloadClass &objRight);
// == 操作符重载,作为成员函数
bool operator==(const OverloadClass &objToCompare);
// == 操作符重载,前缀表达式
bool operator==(const OverloadClass &objLeft, const OverloadClass &objRight)
{
if(objLeft.productName != objRight.productName)
return false;
if(objLeft.productQuantiy != objRight.productQuantiy)
return false;
if(objLeft.productPrice != objRight.productPrice)
return false;
return true;
}
// 操作符重载,类成员函数
bool OverloadClass::operator==(const OverloadClass &objToCompare)
{
if(objToCompare.productName != this->productName)
return false;
if(objToCompare.productQuantiy != this->productQuantiy)
return false;
if(objToCompare.productPrice != this->productPrice)
return false;
return true;
}
六、[]下标运算符
只能定义在类成员函数中
七、++自增运算符
前缀自增运算符和后缀自增运算符怎么区别,一个加一个int参数,在调用的时候传入实参0
- 前缀自增运算符
- 后缀自增预算符
//=======================注意前后缀表达式的区别在哪里?
// ++自增操作符重载,前缀表达式
int operator++();
// ++自增操作符重载,后缀表达式
int operator++(int); // 一般使用0作为实参
int OverloadClass::operator++()
{
return intVector[++vecIndex];
}
int OverloadClass::operator++(int)
{
return intVector[vecIndex++];
}
注意上面两个函数的返回值不一样
八、=赋值运算符
赋值操作符重载,注意赋值必须返回对*this的引用
九、*解引用运算符
十、->运算符
在调用p->action中主要看p是对象,还是指针,
C++ Primer中写道:
根据以下三个步骤执行
1、如果p是一个指针,那么直接执行p的成员函数action
2、如果p不是一个指针而是一个对象,那么执行p的->重载函数,相当于p.opeator->()->action,假设m=p.opeator->(),那么判断m是一个指针还是一个对象,从第一步开始执行;
3、其他情况出错
用一段代码来解释一下
GrandFather类
#pragma once
#include <string>
#include <iostream>
using namespace std;
class GrandFather
{
public:
GrandFather(void);
~GrandFather(void);
void action()
{
cout<<"GrandFather's action"<<endl;
}
GrandFather *operator->()
{
cout<<"进入重载"<<endl;
return this;
}
};
Father类
#pragma once
#include <iostream>
#include <string>
#include "GrandFather.h"
using namespace std;
class Father
{
public:
Father(void);
~Father(void);
GrandFather *pGrandFather;
GrandFather grandFather;
void action()
{
cout<<"Father's action"<<endl;
}
GrandFather *operator->()
{
return pGrandFather;
}
//GrandFather operator->()
//{
// return grandFather;
//}
};
Child类
#pragma once
#include <iostream>
#include "Father.h"
using namespace std;
class Child
{
public:
Child(void);
~Child(void);
Father *pFather;
Father father;
void action()
{
cout<<"Child's action"<<endl;
}
//Father *operator->()
//{
// return pFather;
//}
Father operator->()
{
return father;
}
};
运行以下代码
cout<<"->操作符重载"<<endl;
Child *pChild, child;
pChild = new Child;
pChild->action(); // 执行action函数
child->action(); // 先执行Child重载函数->然后得到一个Father对象执行它的->函数,
//得到一个GrandFather对象指针,执行Grandfather的函数,关键是看是对象还是对象的指针
得到的结果是
Child’s action
GrandFather’s action
注意,小弟有个问题请教在Father类中,
GrandFather *operator->()
{
return pGrandFather;
}
pGrandFather没有分配内存空间,为什么没有报内存泄露的错,请大神指教