运算符重载(operator overloading)只是一种”语法上的方便”,也就是它只是另一种函数调用的方式。运算重载符是多态的一种表现。
对于内置数据类型,编译器知道如何做运算。
1.加号运算符重载
- 如果想让自定义数据类型 进行+运算,那么就需要重载 + 运算符
- 在成员函数 或者 全局函数里 重写一个+运算符的函数
- 函数名 operator+ () {}
- 运算符重载 也可以提供多个版本
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
Person(){};
Person(int a, int b) :m_A(a), m_B(b)
{
}
+运算符重载 成员函数
//Person operator+ (Person & p)
//{
// Person tmp;
// tmp.m_A = this->m_A + p.m_A;
// tmp.m_B = this->m_B + p.m_B;
// return tmp;
//}
int m_A;
int m_B;
};
//利用全局函数 进行+号运算符的重载
Person operator+ (Person &p1, Person &p2)
{
Person tmp;
tmp.m_A = p1.m_A + p2.m_A;
tmp.m_B = p1.m_B + p2.m_B;
return tmp;
}
//利用全局函数 进行+号运算符的重载
Person operator+ (Person &p1, int a)
{
Person tmp;
tmp.m_A = p1.m_A + a;
tmp.m_B = p1.m_B + a;
return tmp;
}
void test01()
{
Person p1(10, 10);
Person p2(10, 10);
Person p3 = p1 + p2; //从什么方式进行转变的? p1.operator+(p2) operator+(p1,p2)
Person p4 = p1 + 2;
cout << "p3的m_A: " << p3.m_A << endl;
cout << "p3的m_B:" << p3.m_B << endl;
cout << "p4的m_A: " << p4.m_A << endl;
cout << "p4的m_B:" << p4.m_B << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
2.左移运算符重载
- 不要随意乱用符号重载
- 内置数据类型 的运算符不可以重载
- cout << 直接对Person自定义数据类型 进行输出
- 写到全局函数中 ostream& operator<< ( ostream & cout, Person & p1 ) {}
- 如果重载时候想访问 p1的私有成员,那么全局函数要做Person的友元函数
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
friend ostream& operator<<(ostream &cout, Person &p1);
public:
Person(){}
Person(int a,int b)
{
this->m_A = a;
this->m_B = b;
}
/*void operator<<()
{
}*/ //重载左移运算符不能写到成员函数中 因为不能 p1<<....
private: //建议将属性设为私有
int m_A;
int m_B;
};
ostream& operator<<(ostream &cout, Person &p1) //第一个参数cout 第二个参数p1
{
cout << "m_A=" << p1.m_A << ", m_B=" << p1.m_B <<endl;
return cout;
}
void test01()
{
Person p1(10, 10);
//cout << p1.m_A << endl;
cout << p1 ; //输出一个Person类型,需要重载左移运算符
}
int main()
{
test01();
system("pause");
return 0;
}
3.前置 后置 ++ 运算符重载
- 自己实现int类型 MyInteger
- 内部维护以int数据
- MyInteger myInt
- myInt ++ 后置 ++myInt 前置
- 重载++运算符 operator++() 前置 operator++(int) 后置
- 前置理念 先++ 后返回自身 后置理念 先保存住原有值 内部++ 返回临时数据
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class MyInteger
{
friend ostream& operator<<(ostream& cout, MyInteger &myInt);
public:
MyInteger()
{
m_Num = 0;
};
//前置++重载
MyInteger& operator++()
{
this->m_Num++;
return *this;
}
//后置++重载(利用占位参数来区分前置和后置)
MyInteger operator++(int)
{
//先保存目前数据
MyInteger tmp = *this;
m_Num++;
return tmp;
}
int m_Num;
};
ostream& operator<<(ostream& cout, MyInteger &myInt)
{
cout << myInt.m_Num ;
return cout;
}
void test01()
{
MyInteger myInt;
//前置++
cout << ++myInt << endl;
//后置++
cout << myInt++ << endl;
cout << myInt << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
前置 后置 - - 运算符重载:只需将上面的++改为--
前置++重载返回的是引用,而后置++重载返回的是值,注意区分。如果前置++重载返回的不是引用,那么就会得到它原先的值。
4.指针重载实现
- Person类有showAge 成员函数
- 如果new出来的Person对象,就要让程序员自觉的去释放 delete
- 有了智能指针,让智能指针托管这个Person对象,对象的释放就不用操心了,让智能指针管理
- 为了让智能指针像普通的Person*指针一样使用 就要重载 -> 和*
指针和*的重载
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
Person(int age)
{
this->m_Age = age;
}
void showAge()
{
cout << "年龄为: " << this->m_Age << endl;
}
~Person()
{
cout << "Person的析构调用" << endl;
}
int m_Age;
};
//智能指针
//用来托管自定义类型的对象,让对象进行自动的释放
class smartPointer
{
public:
smartPointer(Person *person)
{
this->person = person;
}
//重载->让智能指针对象 像Person *p一样使用
Person* operator->()
{
return this->person;
}
//重载*
Person& operator*()
{
return *this->person;
}
~smartPointer()
{
cout << "智能指针析构" << endl;
if (this->person != NULL)
{
delete this->person;
this->person = NULL;
}
}
private:
Person *person;
};
void test01()
{
//Person p1(10); //自动析构
//Person *p1 = new Person(10);
//p1->showAge
//delete p1; 没有做及时清理就出现智能指针
smartPointer sp(new Person(10)); //有参构造调用,维护指针,开辟到栈上
sp->showAge(); //sp->->showAge() 编译器优化了写法
(*sp).showAge();
}
int main()
{
test01();
system("pause");
return 0;
}
5.赋值运算符重载
- 系统默认给类提供 赋值运算符写法 是简单值拷贝
- 导致如果类中有指向堆区的指针,就可能出现深浅拷贝的问题
- 所以要重载 = 运算符
- 如果想链式编程 return*this
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//一个类默认创建 默认构造、析构、拷贝构造、=赋值运算符(简单的值传递)
class Person
{
public:
Person(int a)
{
this->m_A = a;
}
int m_A;
};
class Person2
{
public:
Person2(char *name)
{
this->pName = new char[strlen(name) + 1];
strcpy(this->pName, name);
}
//重载=
Person2& operator=(const Person2 &p)
{
//判断原来已经堆区有内容,先释放
if (this->pName != NULL)
{
delete[] this->pName;
this->pName = NULL;
}
this->pName = new char[strlen(p.pName) + 1];
strcpy(this->pName, p.pName);
return *this;
}
~Person2()
{
if (this->pName != NULL)
{
delete[] this->pName;
this->pName = NULL;
}
}
char* pName;
};
void test02()
{
Person2 p1("狗蛋");
Person2 p2("狗剩");
/*p2 = p1;
cout << p2.pName << endl;*/
Person2 p3("");
p3 = p2 = p1;
cout << "p3.pName=" << p3.pName << endl;
}
void test01()
{
Person p1(10);
Person p2(0);
p2 = p1; //赋值
cout << "p2的m_A等于:" << p2.m_A << endl;
}
int main()
{
//test01();
test02();
system("pause");
return 0;
}
6. []运算符重载
- 返回数组索引的引用
- int & operator[](int index)
- return this->pAddress[index]
源文件
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include"MyArray.h"
void test01()
{
//堆区创建数组
MyArray * array = new MyArray(30);
//不调用拷贝构造
//MyArray * array2(array);
//MyArray * array2 = array;
//调用拷贝构造
MyArray *array2 = new MyArray(*array);
MyArray array3 = *array;
//尾插法测试
for (int i = 0; i < 10; i++)
{
array2->Push_Back(i);
}
//获取数据测试
for (int i = 0; i < 10; i++)
{
cout << array2->getData(i) << endl;
}
//设置值测试
array2->setData(0, 1000);
cout << array2->getData(0) << endl;
//获取数组大小
cout << "array2的数组大小为:" << array2->getSize() << endl;
//获取数组容量
cout << "array2的数组容量为:" << array2->getCapacity() << endl;
//获取 设置 数组内容 如何用[]进行设置和访问
array3.Push_Back(100000);
cout << array3.getData(0) << endl;
cout << array3[0] << endl;
//array3[0] = 100; //100000=100 改为&
array3[0] = 100;
cout << array3[0] << endl;
delete array;
}
int main()
{
test01();
system("pause");
return 0;
}
MyArray.cpp
#include"MyArray.h"
//默认构造
MyArray::MyArray()
{
this->m_Capacity = 100;
this->m_Size = 0;
this->pAddress = new int[this->m_Capacity];
}
//有参构造 参数 数组容量
MyArray::MyArray(int capacity)
{
//cout << "有参调用" << endl;
this->m_Capacity = capacity;
this->m_Size = 0;
this->pAddress = new int[this->m_Capacity];
}
//拷贝构造
MyArray::MyArray(const MyArray& array)
{
cout << "拷贝构造调用" << endl;
this->pAddress = new int[array.m_Capacity];
this->m_Size = array.m_Size;
this->m_Capacity = array.m_Capacity;
for (int i = 0; i < array.m_Size; i++)
{
this->pAddress[i] = array.pAddress[i];
}
}
//析构
MyArray::~MyArray()
{
if (this->pAddress != NULL)
{
//cout << "调用析构" << endl;
delete[] this->pAddress;
this->pAddress = NULL;
}
}
void MyArray::Push_Back(int val)
{
//判断越界? 不需要 用户自己处理
this->pAddress[this->m_Size] = val;
this->m_Size++;
}
int MyArray::getData(int index)
{
return this->pAddress[index];
}
void MyArray::setData(int index, int val)
{
this->pAddress[index] = val;
}
int MyArray::getSize()
{
return this->m_Size;
}
int MyArray::getCapacity()
{
return this->m_Capacity;
}
//[]重载实现
int& MyArray::operator[](int index)
{
return this->pAddress[index];
}
MyArray.h
#pragma once
#include<iostream>
using namespace std;
class MyArray
{
public:
MyArray(); //默认构造 默认100个容量
MyArray(int capacity);
MyArray(const MyArray& array);
~MyArray();
//尾插法
void Push_Back(int val);
//根据索引获取值
int getData(int index);
//根据索引设置值
void setData(int index, int val);
//获取数组大小
int getSize();
//获取数组容量
int getCapacity();
//[]运算符重载
int& operator[](int index);
private:
int *pAddress; //指向真正存储数据的指针
int m_Size; //数组大小
int m_Capacity; //数组容量
};