(黑马C++)L05 运算符重载

一、强化训练---数组类封装

实现数组的功能,成员变量包括数组的容量,大小;实现的功能包括根据位置添加元素、获取指定位置的数据、尾插法、获得数组的长度。

//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 getVal(int index);

	//根据索引设置值
	void setVal(int index, int val);

	//获取数组的大小
	int getSize();

	//获取数组的容量
	int getCapacity();

private:
	int* pAddress; //指向真正存储数据的指针
	int m_size; //数组大小
	int m_capacity; //数组容量
};


//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)
{
	this->pAddress = new int[array.m_capacity];
	this->m_capacity = array.m_capacity;
	this->m_size = array.m_size;
	for (int i = 0; i < array.m_capacity; 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::getVal(int index)
{

	return this->pAddress[index];
}

void MyArray::setVal(int index, int val)
{
	this->pAddress[index] = val;
}

int MyArray::getSize()
{
	return this->m_size;
}

int MyArray::getCapacity()
{
	return this->m_capacity;
}



//数组类的封装.cpp
#include<iostream>
#include "MyArray.h"

void test() {
	MyArray* myArray = new MyArray(10);
	//MyArray* myArray2(myArray); 这是声明一个指针和myArray地址相同,不会调用拷贝构造
	MyArray* myArray2 = new MyArray(*myArray); //new方式调用构造函数
	//尾插测试
	for (int i = 0; i < 5; i++) {
		myArray2->push_back(i);
	}
	//获取数据测试
	for (int i = 0; i < 5; i++) {
		int tmp = myArray2->getVal(i);
		cout << tmp << endl;
	}
	//设置数据测试
	myArray2->setVal(0, 20);
	cout << myArray2->getVal(0) << endl;
	//获取数组大小测试
	cout << "数组的大小为:" << myArray2->getSize() << endl;
	//获取数组容量的测试
	cout << "数组的容量为:" << myArray2->getCapacity() << endl;
}

using namespace std;
int main() {
	test();
	system("pause");
	return 0;
}

二、加号运算符的重载

对于内置的数据类型,编译器知道如何做运算,通过运算符重载可以实现对其他类型的数据进行运算,运算符的重载可以有多个版本。

(1)成员函数实现相加

例如:实现两个Person对象相加,常规写法如下

Person plusPerson(Person &p) {
    Person tmp;
    tmp.m_A = this->m_A + p.m_A;
    tmp.m_B = this->m_B + p.m_B;
    return tmp;
}

以上方法实现两个Person对象相加时,需要用p1.plusPerson(p2)进行运算。

加号重载的实现方法:

1.将函数名改为operator+;2.此时两成员进行运算可以直接写成p1+p2。

(2)全局函数实现相加

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类型,而不是只能输出里面的成员变量。

#include <iostream>
using namespace std;

class Person{
public:
    Person() {}; //默认构造
    Person(int a, int b) { //有参构造
        this -> m_A = a;
        this -> m_B = b;
    };
    int m_A;
    int m_B;

};

//重载左移运算符不可写在成员函数中
//如果在成员函数中调用需要写成p<<
ostream& operator<< (ostream& cout, Person& p) { //第一个参数cout 第二个参数p
    cout << "m_A = " << p.m_A << "m_B = " << p.m_B << endl;
    return cout; //return cout后test中才能拼接换行
}

void test() {
    Person p1(10, 10);
    cout << p1 << endl; //左移运算符重载后可以直接输出Person类型
}

int main() {
    test();
    system("pause");
    return 0;
}

四、前置后置递增运算符重载

class MyInt{
public:
    MyInt() {
        num = 0;
    };

    int num;
    
    //前置++重载
    MyInt& operator++() {
        this->num++;
        return *this;
    }

    //后置++重载
    MyInt operator++(int) { //与前置++区分
        MyInt tmp = *this;
        this->num++;
        return tmp;
    }
};

ostream& operator<< (ostream& cout, MyInt& myint) {
    cout << myint.num;
    return cout;
}

void test() {
    MyInt myint;
    //前置++
    cout << ++myint << endl;

    //后置++
    cout << myint++ << endl;

    //myint结果
    cout << myint << endl;
}

int main() {
    test();
    system("pause");
    return 0;
}

前置和后置形式语义上是等价的,输入工作量也相当,只是前置的效率会更高一些,因为前置会少创建一个临时对象。

五、指针运算符重载

#include <iostream>
using namespace std;

class Person{
public:
    void showAge() {
        cout <<"年龄为:" << m_age << endl;
    }

    Person(int age) {
        m_age = age;
    }

    ~Person() {
        cout << "析构函数的调用" << endl;
    }
    int m_age;
};

//智能指针
//用来托管自定义的对象,让对象自动释放
class smartPerson{
public:
    smartPerson(Person* person) {
        this->person = person;
    }
    
    //重载->让智能指针的对象可以和person对象一样去使用
    Person* operator->() {
        return this->person;
    }
    
    //重载*
    Person& operator*() {
        return *(this->person);
    }
    

    ~smartPerson() {
        cout << "智能指针的析构" << endl;
        if(this->person != NULL) {
            delete this->person;
            this->person = NULL;
        }
    }

private:
    Person* person;
};

void test() {
    //开辟在栈上,自动析构
    Person p1(10); 
    //开辟在堆上,需要delete
    Person* p2 = new Person(10); 
    delete p2;
    //智能指针
    smartPerson sp(new Person(10)); //sp开辟到了栈上,会自动析构
    sp->showAge();
    (*sp).showAge();
}

int main() {
    test();
    system("pause");
    return 0;
}

六、赋值运算符重载

#include <iostream>
using namespace std;

//一个类默认创建 默认构造、析构、拷贝构造、operator=赋值运算符 进行简单的值传递
class Person{
public:
    Person(int a) {
        m_a = a;
    }

    int m_a;
};


void test() {
    Person p1(10); 
    Person p2(20); 
    //赋值运算符,会调用默认的重载
    p1 = p2;
    cout << "p2的m_a为:" << p2.m_a << endl;
}


class Person2{
public:
    Person2(char* name) {
        this->p_name = new char[strlen(name)+1];
        strcpy(this->p_name, name);
    }
    
    //重载=赋值运算符
    //返回Person2的引用后才可以连等
    Person2& operator= (Person2& p) {
        //判断原来堆区的内容
        if(this->p_name != NULL) {
            delete[] this->p_name;
            this->p_name = NULL;
        }
        //重新开辟一段空间
        this->p_name = new char[strlen(this->p_name)+1];
        strcpy(this->p_name, p.p_name);
        return *this;
    }

    ~Person2() {
        if(this->p_name != NULL) {
            delete[] this->p_name;
            this->p_name = NULL;
        }
    }

    char* p_name;
};

void test02() {
    Person2 p1("狗蛋");
    Person2 p2("狗剩");
    p2 = p1; //如果不进行重载,在析构时会出现深拷贝浅拷贝的问题
    cout << "p2的名字为:" << p2.p_name << endl;
}


int main() {
    test();
    test02();
    system("pause");
    return 0;
}

七、[]运算符重载

//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 getVal(int index);

	//根据索引设置值
	void setVal(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;
	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)
{
	this->pAddress = new int[array.m_capacity];
	this->m_capacity = array.m_capacity;
	this->m_size = array.m_size;
	for (int i = 0; i < array.m_capacity; 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::getVal(int index)
{

	return this->pAddress[index];
}

void MyArray::setVal(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];
}

//数组类的封装.cpp
#include<iostream>
#include "MyArray.h"

void test() {
	MyArray* myArray = new MyArray(10);
	//MyArray* myArray2(myArray); 这是声明一个指针和myArray地址相同,不会调用拷贝构造
	MyArray* myArray2 = new MyArray(*myArray); //new方式调用构造函数
	//尾插测试
	for (int i = 0; i < 5; i++) {
		myArray2->push_back(i);
	}
	//获取数据测试
	for (int i = 0; i < 5; i++) {
		int tmp = myArray2->getVal(i);
		cout << tmp << endl;
	}
	//设置数据测试
	myArray2->setVal(0, 20);
	cout << myArray2->getVal(0) << endl;
	//获取数组大小测试
	cout << "数组的大小为:" << myArray2->getSize() << endl;
	//获取数组容量的测试
	cout << "数组的容量为:" << myArray2->getCapacity() << endl;
    //获取数组内容,直接用[]进行设置访问
    cour << myarray2[0] << endl;
}

using namespace std;
int main() {
	test();
	system("pause");
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值