1.加号运算符重载
如果想让自定义的数据类型进行+运算,那么就需要重载 + 运算符
重载+运算符时可以选择在成员函数或者全局函数中重写一个+运算符的函数
结构:函数名 operator+ () {}
第一种
class Person
{
public:
Person() { m_A = 0, m_B = 0; };
Person(int a, int b) :m_A(a), m_B(b)
{}
//+号运算符重载,成员函数
Person operator+(Person& p)
{
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}
int m_A;
int m_B;
};
void test()
{
Person p1(9, 111);
Person p2(9, 111);
Person p3 = p1 + p2;//关键字operator可以省略不写
cout << p3.m_A << endl;//18
cout << p3.m_B << endl;//222
}
第二种
class Person
{
public:
Person() { m_A = 0, m_B = 0; };
Person(int a, int b) :m_A(a), m_B(b)
{}
int m_A;
int m_B;
};
//利用全局函数进行+号运算符的重载
Person operator+(Person& p1, Person& p2)
{
Person temp;
temp.m_A = p1.m_A + p2.m_A;
temp.m_B = p1.m_B + p2.m_B;
return temp;
}
void test()
{
Person p1(9, 111);
Person p2(9, 111);
Person p3 = p1 + p2;//关键字operator可以省略不写
cout << p3.m_A << endl;//18
cout << p3.m_B << endl;//222
}
2.左移运算符重载
要注意:不要随意乱用符号重载;内置数据类型(如int)的运算符不可以重载
左移运算符cout<<是为了对自定义的数据类型进行输出
class Person
{
//如果重载时候想访问 p1的私有成员,那么全局函数要做Person的友元函数
friend ostream& operator<<(ostream& cout, Person& p);
public:
Person() { m_a = 0, m_b = 0; };
Person(int a, int b)
{
this->m_a = a;
this->m_b = b;
}
//void operator<<()//重载左移运算符不可以写到成员函数中,因为在调用的时候会出现值在cout<<左边的情况,但我们需要的是cout<<值。
//{
//}
private:
int m_a;
int m_b;
};
//ostream是c++中的输出流,是一个定义输出到显示(输出)设备上的一个类&c++中表示引用,即使用的当前值,而不是通过自动复制的
ostream& operator<<(ostream& cout, Person& p)//第一个参数cout 第二个参数p1
{
cout << "m_a = " << p.m_a << "m_b = " << p.m_b;
return cout;//可做左值
}
void test()
{
Person p1(10, 10);
cout << p1 << endl;
//operator<<(cout, p1);
cout << p1 <<"hello" << endl;
}
3.前置后置的递增递减运算符重载
前置理念——先++ 后返回自身
后置理念——先保存住原有值 ,内部++ 返回临时数据
class MyInteger
{
friend ostream& operator<<(ostream& cout, const MyInteger& myint);
public:
MyInteger()
{
m_num = 0;
}
//重载++运算符 operator++() 前置 operator++(int) 后置
//前置++重载 返回引用
MyInteger& operator++()
{
this->m_num++;
return *this;
}
//后置++重载 返回值
MyInteger operator++(int)
{
//先保存目前数据
MyInteger temp = *this;
m_num++;
return temp;//临时数据
}
//前置--重载
MyInteger& operator--()
{
this->m_num--;
return *this;
}
//后置--重载
MyInteger operator--(int)
{
//先保存目前数据
MyInteger temp = *this;
m_num--;
return temp;
}
int m_num;
};
ostream& operator<<(ostream& cout, const MyInteger& myint)
{
cout << myint.m_num;
return cout;
}
void test()
{
MyInteger myint;
myint++;//后置++
++myint;//前置++
cout << ++(++myint) << endl;
cout << myint << endl;
cout << myint++ << endl;
cout << myint.m_num << endl;
}
4.指针运算符重载
class Person
{
public:
Person(int Age)
{
this->age = Age;
}
void showage()
{
cout << "年龄为:" << this->age << endl;
}
~Person()
{
cout << "析构函数调用" << endl;
}
int age;
};
//智能指针,用来托管自定义类型的对象,让对象进行自动释放
class smartPointer
{
public:
smartPointer(Person* person)
{
this->person = person;
}
//重载->让智能指针对象像Person * p一样使用
Person* operator->()
{
return this->person;
}
//重载*
Person& operator*()
{
return *this->person;
}
~smartPointer()
{
cout << "smartPointer析构调用" << endl;
if (this->person != NULL)
{
delete this->person;
this->person = NULL;
}
}
private:
Person* person;
};
//有了智能指针,让智能指针托管这个Person对象,对象的释放就不用操心了,让智能指针管理
//为了让智能指针想普通的Person*指针一样使用 就要重载 -> 和*
void test()
{
//Person p1(18);//开辟在栈上,自动析构
//Person* p1 = new Person(18);//开辟在堆上
//p1->showage();
//delete p1;
//如果new出来的Person对象,就要让程序员自觉的去释放 delete
smartPointer sp(new Person(18));//开辟到了栈上,自动释放
sp->showage();//sp->->showage();编译器优化了写法
(*sp).showage();
}
5.赋值运算符重载
//一个类默认创建默认构造、析构、拷贝构造、operator=赋值运算符 进行简单的值传递
class Person
{
public:
Person(int a)
{
this->m_a = a;//int类型
}
int m_a;
};
void test()
{
Person p1(10);
Person p2(0);
p2 = p1;//赋值
cout << p2.m_a << endl;
}
class Person2
{
public:
Person2(const 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 test2()
{
Person2 p1("狗蛋");
Person2 p2("狗剩");
Person2 p3("");
p3 = p2 = p1;
cout << p3.pname << endl;
}
6.强化训练-数组类的封装
首先建立头文件MyArray.h
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;//数组的容量
};
然后再MyArray.cpp文件中对相应的函数进行声明
#include "MyArray.h"
//默认构造
MyArray::MyArray()
{
this->m_Capacity = 100;//默认100容量
this->m_Size = 0;//默认数组的大小为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()
{
cout << "析构函数调用" << endl;
if (this->pAddress != NULL)
{
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];
}
测试案例
void test()
{
//堆区创建数组
MyArray* array = new MyArray(30);
MyArray* array2 = new MyArray(*array);//new方法来指定调用拷贝构造函数
MyArray array3 = *array; //构造函数返回的本体
MyArray* array4 = new MyArray(*array);
delete array;
//MyArray * array4 = array;
//这个是声明一个指针,和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;//100000
cout << array3[0] << endl;//100000
array3.getData(0) = 4;
cout << array3.getData(0) << endl;//4
array3[0] = 100; // 100000 = 100
cout << array3[0] << endl;//100
/*cout << array4[0] << endl;
array4[0] = 10;*/
}