一 概念
1为什么会用运算符重载机制
用复数类举例/
/Complex c3 =c1 + c2;
//原因 Complex是用户自定义类型,编译器根本不知道如何进行加减
//编译器给提供了一种机制,让用户自己去完成,自定义类型的加减操作。。。。。
//这个机制就是运算符重载机制
2 运算符重载的本质是一个函数
全局函数、类成员函数方法实现运算符重载步骤
1)要承认操作符重载是一个函数,写出函数名称operator+ ()
2)根据操作数,写出函数参数
3)根据业务,完善函数返回值(看函数是返回引用 还是指针 元素),及实现函数业务
void main()
{
Complex c1(1, 2), c2(3, 4);
//Complex c3 = c1 + c2; //用户自定义类型 编译器无法让变量相加
//Complex myAdd(Complex &c1, Complex &c2);
//1 普通函数
//Complex c3 = myAdd(c1, c2);
//c3.printCom();
//2 operator+ 函数名称
//Complex c3 = operator+(c1, c2);
//c3.printCom();
//3 +替换 函数名
Complex c3 = c1 + c2; //思考C++编译器如何支持操作符重载机制的 (根据类型)
c3.printCom();
{
int a =0, b = 0, c; //基础类型C++编译器知道如何加减
c = a +b;
}
//4 把Complex类变成私有属性
//友元函数的应用场景
//friend Complex operator+(Complex &c1, Complex &c2);
cout<<"hello..."<<endl;
system("pause");
return;
}
二 运算符重载的限制
三 运算符重载编程基础
例如:
//全局函数(友元函数) 完成 +操作符 重载
Complex operator+(Complex &c1, Complex&c2)
//类成员函数 完成 -操作符 重载
Complex operator-(Complex &c2)
1. 运算符重载的两种方法
2. 二元运算符重载
例如1:
//通过类成员函数完成-操作符重载
//函数声明 Complex operator-(Complex &c2)
//函数调用分析
//用类成员函数实现-运算符重载
Complex c4 = c1 - c2;
c4.printCom();
//c1.operator-(c2);
例如2:
//通过全局函数方法完成+操作符重载
//函数声明 Complex operator+(Complex&c1, Complex &c2)
//函数调用分析
int main()
{
Complex c1(1, 2), c2(3, 4);
//Complex c31 = operator+(c1,c2);
Complex c3 = c1 + c2;
c3.printCom();
}
3. 一元运算符重载
例如3
//前置++操作符
用全局函数(友元函数)实现
Complex& operator++(Complex &c1)
{
c1.a ++;
c1.b ++;
return c1;
}
//调用方法
++c1 ; //需要写出操作符重载函数原形
c1.printCom();
//运算符重载函数名定义
//首先承认操作符重载是一个函数
定义函数名operator++
//分析函数参数
根据左右操作数的个数,operator++(Complex &c1)
//分析函数返回值Complex& operator++(Complex &c1) 返回它自身
例如4
//4.1前置—操作符 成员函数实现
Complex& operator--()
{
this->a--;
this->b--;
return *this;
}
//4.2调用方法
--c1;
c1.printCom();
//4.3前置—运算符重载函数名定义
//c1.operator--()
例如5
//5.1
//后置++ 操作符 用全局函数实现
Complex operator++(Complex &c1, int) //多一个int
{
Complex tmp = c1;//先调用,后++
c1.a++;
c1.b++;
return tmp;
}
//5.2 调用方法
c1 ++ ; //先使用 后++
//5.3 后置++运算符重载函数名定义
Complex operator++(Complex &c1, int) //函数占位参数和 前置++ 相区别
例如6
//6.1 后置— 操作符
用类成员函数实现
Complex operator--(int)
{
Complex tmp = *this;
this->a--;
this->b--;
return tmp;
}
//6.2 调用方法
c1 ++ ; //先使用 后++
//6.3 后置–运算符重载函数名定义
Complex operator--(int) //函数占位参数 和 前置-- 相区别
4. 友元函数实现操作符重载的应用场景
1)友元函数和成员函数选择方法
Ø 当无法修改左操作数的类时,使用全局函数进行重载
Ø =, [], ()和->操作符只能通过成员函数进行重载
2)用友元函数 重载 << >>操作符
Ø istream 和 ostream 是 C++ 的预定义流类
Ø cin 是 istream 的对象,cout 是 ostream 的对象
Ø 运算符 << 由ostream 重载为插入操作,用于输出基本类型数据
Ø 运算符 >> 由 istream 重载为提取操作,用于输入基本类型数据
Ø 用友员函数重载 << 和 >> ,输出和输入用户自定义的数据类型
a)用全局函数方法实现 << 操作符
ostream& operator<<(ostream &out, Complex &c1)
{
//out<<"12345,生活真是苦"<<endl;
out<<c1.a<<"+ "<<c1.b<<"i "<<endl;
return out;//返回一个引用当左值
}
//调用方法
cout<<c1;
//链式编程支持
cout<<c1<<"abcc";
//cout.operator<<(c1).operator<<("abcd");
//函数返回值充当左值
需要返回一个引用
b)类成员函数方法无法实现 << 操作符重载
//因**无法**拿到cout这个类的源码
//cout.operator<<(c1);
3) 友元函数重载操作符使用注意点
a) 友员函数重载运算符常用于运算符的左右操作数类型不同的情况
b)其他
1 在第一个参数需要隐式转换的情形下,使用友员函数重载运算符是正确的选择
2 友员函数没有 this 指针,所需操作数都必须在参数表显式声明,很容易实现类型的隐式转换
3 C++中不能用友员函数重载的运算符有
= () [] ->
四 运算符重载提高
1 重载赋值运算符=
Ø 赋值运算符重载用于对象数据的复制
Ø operator= 必须重载为成员函数
//可以做左值,需要返回引用,友元函数里没有this指针
Ø 重载函数原型为:
类型 & 类名 :: operator= ( const 类名 & ) ;
案例:完善Name类,支持=号操作。
结论:
1//先释放旧的内存
2返回一个引用
3=操作符 从右向左
//obj3 = obj1;
// C++编译器提供的 等号操作 也属 浅拷贝
// obj4 = obj3 = obj1
//obj3.operator=(obj1)
Name&
operator=(Name &obj1)
{
//1 先释放obj3旧的内存
if(this->m_p != NULL)
{
delete[] m_p;
m_len = 0;
}
//2 根据obj1分配内存大小
this->m_len= obj1.m_len;
this->m_p= new char [m_len+1];
//3把obj1赋值给obj3
strcpy(m_p,obj1.m_p);
return *this;