一、强化训练---数组类封装
实现数组的功能,成员变量包括数组的容量,大小;实现的功能包括根据位置添加元素、获取指定位置的数据、尾插法、获得数组的长度。
//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;
}