前言:
仅做记录和分享自己学习的过程,学艺不精,code新人,如有错误欢迎在评论区讨论、指正!
C++中预定义的操作符对象只能是基本数据类型,想要对自定义的类进行相似的运算操作,需要重新定义这些运算符,实现想要的运算功能(本质类似函数重载)
一、运算符重载实现的方式
1.成员函数实现
a1+a2 相当于 a1.operator+(a2), 在A类中实现该函数
语法形式:
class 类名
{
返回类型 operator运算符(形参表);
}
类外定义格式
返回类型 类名::operator运算符(形参表)
{
函数体;
}
2.友元函数实现
a1+a2 相当于operator+(a1,a2),在全局函数中实现
class 类名
{
friend 返回类型 operator运算符(形参表);
}
类外定义格式
返回类型 operator运算符(形参表)
{
函数体;
}
对于成员函数重载运算符而言,双目运算符的参数表中仅有一个参数,而单目则无参数。同样的是重载,友元函数在参数的个数上会有所区别的。原因在于友元函数,没有this指针。
二、特殊的成员函数
特殊在,如果没有自己写,编译系统会自动生成简单的默认版本,默认版本功能比较简单,只能保证基本的编译通过,当涉及到空间的开辟和销毁时,最好自己写这些函数。
1.构造函数
默认的构造函数,没有参数, 没有做事情
例如,A();
2.析构函数
默认的析构函数,没有参数, 没有做事情
例如 ,~A();
3.拷贝函数
默认的拷贝构造, 浅拷贝,相当于直接赋值,不会开空间,如果在值里面有指针会造成,多变量指向同一空间,在析构的时候可能多次释放同一片空间,造成错误。
4.赋值函数
默认的赋值函数, 浅拷贝
三、运算符重载实践题
1.数组类Array
完善数组类,实现==, + , +=, [],=,支持cout输出
实现结果截图:
实现代码:
#include <iostream>
using namespace std;
// 设计一个数组类
class Array // 类的声明
{
private:
int *data; // 数组指针,指向数组数据
int length; // 数组长度
int index;//数组最大下标
public:
Array(); // 无参构造函数
Array(int len); // 有参构造函数
Array(int *b, int n); // 拷贝构造函数,传入一个数组
Array(const Array &obj); // 拷贝构造函数,传入一个对象
~Array(); // 析构函数
friend ostream &operator<<(ostream &out,const Array &obj);
friend istream &operator>>(istream &in, Array &obj);
Array &operator=(const Array &obj) // 重载+运算符
{
delete[] data;
int n = obj.index;
index = n;
length = n + 1;
data = new int[length];//动态分配内存
for (int i = 0; i <= n; i++)//赋值
{
data[i] = obj.data[i];
}
return *this;
}
Array operator+(const Array &obj) // 重载+运算符
{
Array arr1;//创建一个新数组对象
arr1.length = index + obj.index + 2;
arr1.index = arr1.length - 1;
arr1.data = new int[arr1.length];
for (int i = 0; i <= index; i++)
{
arr1.data[i] = data[i];
}
for (int i = 0; i <= obj.index; i++)
{
arr1.data[index + 1 + i] = obj.data[i];
}
return arr1;
}
Array &operator+=(const Array &obj) // 重载+=运算符
{
// 在原对象的基础上进行操作
int *new_data = new int[index + obj.index + 2]; // 创建新数组
int new_length = index + obj.index + 2;
int new_index = index + obj.index + 1;
for (int i = 0; i <= index; i++) // 将原数组元素复制到新数组
{
new_data[i] = data[i];
}
for (int i = 0; i <= obj.index; i++) // 将新数组元素复制到新数组
{
new_data[index + 1 + i] = obj.data[i];
}
delete[] data; // 释放原数组
data = new_data; // 更新当前对象
length = new_length;
index = new_index;
return *this;
}
bool operator==(const Array &obj)// 重载==运算符
{
if (index == obj.index && length == obj.length)
{
for (int i = 0; i < index; i++)
{
if (data[i] != obj.data[i])
return false;
}
return true;
}
else
{
return false;
}
}
int& operator[](int index)// 重载[]运算符
{
if (index >= 0 && index <= this->index)
return data[index];
else
{
cout << "数组越界" << endl;
exit(0);
}
}
};
Array::Array() // 无参构造函数
{
length = 10;
data = new int[length];
index = -1;
// cout << "调用无参构造函数" << endl;
}
Array::Array(int len) // 开辟空间
{
data = new int[len];
length = len;
index = -1;
// cout << "调用有参构造函数" << endl;
}
Array::Array(int *b, int n) // 拷贝构造函数,传入一个数组
{
data = new int[n];
length = n;
for (int i = 0; i < n; i++)
{
data[i] = b[i];
}
index = n - 1;
// cout << "调用拷贝构造函数" << endl;
}
Array::~Array() // 析构函数
{
delete[] data; // 回收数组空间
// cout << "调用析构函数" << endl;
}
Array::Array(const Array &obj)
{
data = new int[obj.length];
for (int i = 0; i <= obj.index; i++)
{
data[i] = obj.data[i]; // 拷贝数组
}
length = obj.length;
index = obj.index;
cout << "调用拷贝构造函数" << endl;
}
ostream &operator<<(ostream &out, const Array &obj)
{
for (int i = 0; i <= obj.index; i++)
{
out << obj.data[i] << " ";
}
return out;
}
istream &operator>>(istream &in, Array &obj)
{
in >> obj.index;
for (int i = 0; i <= obj.index; i++)
{
in >> obj.data[i];
}
return in;
}
int main(void)
{
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int b[5] = {11, 22, 33, 44, 55};
Array a1; // 初始化
Array a2(b, 5);
Array a3(a, 10);
a1 = a3; // 赋值
cout << "a1:" << a1 << endl;
cout << "a2:" << a2 << endl;
cout << "a3:" << a3 << endl;
Array a4=a3 + a2;
cout << "a4 = a3 + a2 = :" << a4 << endl;
a1 += a1;
cout << "a1 += a1 = :" << a1 << endl;
if (a1 == a2)
{
cout << "a1==a2" << endl;
}
else
{
cout << "a1!=a2" << endl;
}
cout << "a1[0]="<<a1[0] << endl;
a1[0] = 100;
cout << "a1[0]="<<a1[0] << endl;
cout << "a1[20]="<<a1[20] << endl;
return 0;
}
2.字符串类Mystring
编写Mystring类,实现+,+=,==,=,cout输出,cin输入
实现结果截图:
实现代码:
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
class Mystring
{
public:
Mystring()//无参构造函数
{
str=new char[1];
*str='\0';
}
Mystring(const char *s)//有参构造函数
{
int n = strlen(s);
str=new char[n+1];
strcpy(str,s);
}
Mystring(const Mystring & obj)//拷贝构造函数,一个对象初始化另一个对象
{
int n=strlen(obj.str);
str=new char[n+1];
strcpy(str,obj.str);
}
~Mystring()//析构函数
{
delete [] str;
}
void ShowString() const//显示
{
cout<<str<<endl;
}
int length() const//长度
{
return strlen(str);
}
Mystring operator+(const Mystring &obj) const //+重载
{
Mystring temp;
delete [] temp.str;//释放原本的空间空间
temp.str=new char[strlen(str)+strlen(obj.str)+1];//开辟新空间
strcpy(temp.str,str);
strcat(temp.str,obj.str);
return temp;
}
Mystring & operator+=(const Mystring &obj)//+=重载,开辟新的空间,释放原来的空间
{
char *new_str=new char[strlen(str)+strlen(obj.str)+1];
strcpy(new_str,str);
strcat(new_str,obj.str);
delete [] str;
str=new_str;//重新赋值,浅拷贝,空间转让
return *this;
}
bool operator==(const Mystring &obj) const //==重载,判断
{
if(strcmp(str,obj.str)==0)
return true;
else
return false;
}
Mystring & operator=(const Mystring &obj) //=重载,深拷贝,释放原来的空间,开辟新的空间
{
if(this==&obj)
{
return * this;
}
delete [] str;//释放原来的空间
int n=strlen(obj.str);
str=new char[n+1];
strcpy(str,obj.str);
return *this;
}
friend ostream& operator<<(ostream &out,const Mystring &obj); //cout<<重载
friend istream& operator>>(istream &out,Mystring &obj);//cin>>重载
private:
char *str;
};
ostream& operator<<(ostream &out,const Mystring &obj)
{
out<<obj.str;
return out;
}
istream& operator>>(istream &in,Mystring &obj)//输入流重载,开空间
{
char buf[1024];
in>>buf;
int n=strlen(buf);
delete [] obj.str;
obj.str=new char[n+1];
strcpy(obj.str,buf);
return in;
}
int main()
{
Mystring s1("aaa");//有参构造
cout<<"s1="<<s1<<endl;
Mystring s2("xxx");
cout<<"s2="<<s2<<endl;
Mystring s3;//无参构造
cout<<"请输入s3的值:"<<endl;
cin>>s3;
cout<<"s3="<<s3<<endl;
Mystring s4(s1);//拷贝构造
cout<<"s4="<<s4<<endl;
Mystring str1=s1+s2;//+运算符重载
cout<<"str1=s1+s2="<<str1<<endl;
str1+=str1;//+=运算符重载
cout<<"str1+=str1="<<str1<<endl;
if(s1==s2)//==运算符重载
{
cout<<"s1==s2"<<endl;
}else
{
cout<<"s1!=s2"<<endl;
}
s2=s1;//赋值函数
cout<<"s2=s1="<<s2<<endl;
}