今天知识点不多 但代码量不少知识点也比较重要 希望大佬们坚持住!!!
目录
operator 重载运算符
前面学习过基本运算符,重载则是在已有运算符的基础上重新写一套运算符的实现
应用场景:当我们使用自定义对象进行运算符操作时,相同无法识别。需要重载
例如:打印对象----cout
概述
重载函数: operator
操作步骤:
1.考虑运算符有多少参数个数;确定多少个,则重载时需要写多少个
2.运算符函数的左边是自定义对象还是其他类型
左边:是其他 只能全局函数实现 (必须使用全局友元)
左边:自定义对象
可以用全局友元(参数个数 和 运算符对象的个数一致)
成员函数(参数可以少一个) (推荐
+号运算符重载
自定义类型运算时 系统一般不会提供相应的运算符 所以需要用户重载
class Person
{
public:
Person(){};
Person(int a,int b):m_A(a),m_B(b){}
int m_A;
int m_B;
//类内函数重载 +
// Person operator +(const Person& p)
// {
// Person tmp;
// tmp.m_A = m_A + p.m_A;
// tmp.m_B = m_B + p.m_B;
// return tmp;
// }
};
//类外函数重载 +
Person operator+ (const Person& p1,const 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+ (const Person& p1,const int num)
{
Person tmp;
tmp.m_A = p1.m_A + num;
tmp.m_B = p1.m_B + num;
return tmp;
}
void test_01()
{
Person p1(10,20);
Person p2(5,5);
Person p3 = p1 + p2; //自定义类型运算时 系统一般不会提供相应的运算符 所以需要用户重载
cout<<"p1.m_A = "<<p1.m_A<<endl;
cout<<"p3.m_A = "<<p3.m_A<<endl;
cout<<"p3.m_B = "<<p3.m_B<<endl;
p3 = p1 + 10; //测试运算符重载可以发生函数重载吗
cout<<"p3.m_A + 10 = "<<p3.m_A<<endl;
cout<<"p3.m_B + 10 = "<<p3.m_B<<endl;
}
<<运算符重载
注意事项:cout的数据类型为:ostream
左移运算符只能在类外定义实现 (如果类内实现 无法实现cout在左边)如果想访问类内私有成员 可以将全局函数设为类的友元
class Person
{
public:
Person(int a,int b)
{
this->m_A = a;
this->m_B = b;
}
int m_A;
int m_B;
};
ostream& operator <<(ostream& cout,const Person& p)
{
cout<<p.m_A<<endl;
cout<<p.m_B<<endl;
return cout;
}
void test_01()
{
Person p(10,20);
cout<<p<<"ok"<<endl; //错误 需要重载左移运算符
}
重载>>运算符(输入)
class Person{
friend istream& operator >>(istream &cin,Person &ob);
private:
string name;
int age;
public:
Person(){}
Person(string name,int age){
this->name = name;
this->age = age;
}
};
istream& operator >>(istream &cin,Person &ob)
{
cin>>ob.name>>ob.age;
return cin;
}
void test02(){
Person p2;
cin>>p2;
cout<<"打印对象:"<<p2<<endl;
}
==运算
class Person{
private:
string name;
int age;
public:
Person(){}
Person(string name,int age){
this->name = name;
this->age = age;
}
bool operator ==(Person &ob)
{
return name==ob.name&&age==ob.age; //比较属性的相等
}
};
void test02(){
//Person p("zs",12);
//打印输出的本质:调的是operator(cout,变量)函数
//cout<<p<<endl; //系统不能输出自定义对象
/*
Person p2;
cin>>p2;
cout<<"打印对象:"<<p2<<endl;*/
Person p4("ww",30);
Person p3("ls",30); //重载是都是转为属性的操作
//cout<<"打印对象:"<<(p3+p3)<<endl;
cout<<(p3==p4)<<endl; //0
}
++前置后置递增运算符重载
注意:前置++正常定义 后置++需要在形参添加一个占位符来告诉编译器定义的为后置++
前置++返回的是引用 后置++返回的是值 (前置++比后置++效率更高 因为后置++会调用拷贝构造 创建新的数据)
class Person
{
public:
Person(int age)
{
m_Age = age;
}
int m_Age;
//前置++的重载
Person& operator++()
{
this->m_Age++;
return *this;
}
//后置++的重载
Person operator++(int ) //int 占位符 后置++与前置++通过占位符区分
{
Person temp(0);
temp.m_Age=this->m_Age;
this->m_Age++;
return temp;
}
};
//左移运算符的重载
ostream& operator <<(ostream& cout,const Person& p)
{
cout<<p.m_Age;
return cout;
}
void test_01()
{
Person p(18);
cout<<"++p = "<<++p<<endl; //报错 需要前置++重载
cout<<"p++ = "<<p++<<endl; //报错 需要后置++重载
cout<<"p = "<<p<<endl;
}
前置--和后置--
自己动手写一下前置--和后置--吧😀
定义一个智能指针 指针运算符重载 (了解)
用途:托管new出来的对象的释放
设计一个智能类 内部维护new出来的person类 在析构的时候释放堆区new出来的person对象
class Person
{
public:
Person(int age)
{
cout<<"构造函数"<<endl;
this->m_A = age;
}
void showData()
{
cout<<this->m_A<<endl;
}
~Person()
{
cout<<"Person的析构函数"<<endl;
}
private:
int m_A;
};
class SmartPoint
{
public:
SmartPoint(Person* person)
{
m_person = person;
}
Person* operator->()
{
return m_person;
}
Person& operator*()
{
return *m_person;
}
~SmartPoint()
{
if(this->m_person)
{
delete m_person;
m_person = NULL;
}
}
private:
Person* m_person;
};
// void test_01()
// {
// Person* p = new Person(18);
// p->showData();
// //指针对象不delete的话 不会调用析构函数
// }
void test_01()
{
SmartPoint s(new Person(18)); //定义了一个智能指针类 但是现在体现出它是指针
//所以需要重定义指针->
s->showData();
(*s).showData();
}
=赋值运算符的重载
系统提供四个函数:默认构造函数 拷贝函数 析构函数 赋值函数(operator =)
当类成员有在堆中申请空间的变量成员 就会发生浅拷贝错误
所以 需要重载赋值函数实现深拷贝
需要返回本类引用 适用连续多次赋值操作
class Person
{
public:
Person(char* name, int age)
{
this->m_Name = new char[strlen(name)+1];
strcpy(this->m_Name, name);
this->m_Age = age;
}
Person(Person& p)
{
this->m_Name = new char[strlen(p.m_Name)+1];
strcpy(this->m_Name, p.m_Name);
this->m_Age = p.m_Age;
}
Person& operator= (const Person &p)
{
if (this->m_Name != NULL)
{
delete[]this->m_Name;
m_Name = NULL;
}
this->m_Name = new char[strlen(p.m_Name) + 1];
strcpy(this->m_Name, p.m_Name);
this->m_Age = p.m_Age;
return *this;
}
char* m_Name;
int m_Age;
~Person()
{
if (this->m_Name!=NULL)
{
delete []this->m_Name;
this->m_Name = NULL;
}
}
};
void test_01()
{
Person p1("Tom", 10);
Person p2("Lis", 20);
p2 = p1; //错误需要重载赋值运算符
cout << "p2姓名:" << p2.m_Name << " p2 年龄:" << p2.m_Age << endl;
Person p3 = p2;
cout << "p3姓名:" << p3.m_Name << " p3 年龄:" << p3.m_Age << endl;
}
[]数组运算符重拷贝
需要返回int引用 如果返回int值的话 不可为数组赋值(值不可在赋值号左边) 只可打印
class MyArray
{
public:
//无参构造函数 用户没有指定容量 初始化为10
MyArray();
//有参构造函数 用户指定容量初始化
explicit MyArray(int capacity);
//用户操作接口
//根据位置添加元素
void SetData(int pos,int val);
//获得指定位置数据
int GatDate(int pos);
//尾插法
void PushBack(int val);
//获得长度
int GetLenth();
//析构函数 释放内存空间
~MyArray();
int& operator [](int size)
{
return *(this->pAdress+size);
}
private:
int mCapacity; //数组一共可以容纳多少容量
int mSize; //当前元素的大小
int* pAdress; //指向存储数据的空间
};
//无参构造函数 用户没有指定容量 初始化为10
MyArray::MyArray()
{
mCapacity = 10;
mSize = 0;
pAdress = new int[mCapacity];
}
//有参构造函数 用户指定容量初始化
MyArray::MyArray(int capacity)
{
mCapacity = capacity;
mSize = 0;
pAdress = new int[mCapacity];
}
//用户操作接口
//根据位置添加元素
void MyArray::SetData(int pos,int val)
{
pAdress[pos] = val;
}
//获得指定位置数据
int MyArray::GatDate(int pos)
{
return pAdress[pos];
}
//尾插法
void MyArray::PushBack(int val)
{
pAdress[mSize] = val;
mSize++;
}
//获得长度
int MyArray::GetLenth()
{
return mSize;
}
//析构函数 释放内存空间
MyArray::~MyArray()
{
delete []pAdress;
}
void test_01()
{
MyArray arr;
for(int i=0;i<10;i++)
{
arr.PushBack(100+i);
}
for(int i=0;i<arr.GetLenth();i++)
{
cout<<arr.GatDate(i)<<endl;
}
cout<<"---------------"<<endl;
arr[0] = 1000;
cout<<arr[0]<<endl;
}
int main(int argc, char* argv[])
{
test_01();
return 0;
}
仿函数重载
重载函数调用运算符:为STL算法提供策略。(可完成链式编程的操作)
class Data{
public:
Data& operator()(char * p) //仿函数重载
{
cout<<p;
return *this; //当前对象调的函数,返回*this
}
};
void test01()
{
Data d; //d.operator()("hello")
d("hello")("world")("666");
}
项目:利用类和重载的知识点 写一个自己的string类
内容: 拷贝构造函数的深拷贝 赋值构造函数的深拷贝 析构函数的释放堆内存
重载>> << + == != [] 的知识
#include <iostream>
#include <cstring>
using namespace std;
class Mystring
{
public:
friend ostream& operator<< (ostream& cout,const Mystring& s);
friend istream& operator>> (istream& cin,Mystring& s);
Mystring(){}
Mystring(const char* str)
{
m_Str = new char[strlen(str)+1];
strcpy(m_Str,str);
Str_len = strlen(str)+1;
}
Mystring(const Mystring& s)
{
m_Str = new char[s.Str_len];
strcpy(m_Str,s.m_Str);
Str_len = s.Str_len;
}
~Mystring()
{
if(m_Str != NULL)
{
delete []m_Str;
m_Str = NULL;
}
}
Mystring& operator= (const Mystring& s);
Mystring& operator= (const char* str);
Mystring operator+ (const Mystring& str);
Mystring operator+ (const char* str);
char& operator[] (int num);
bool operator== (const Mystring& str);
bool operator!= (const Mystring& str);
private:
char* m_Str;
int Str_len;
};
char& Mystring::operator[] (int num)
{
return *(m_Str+(num));
}
ostream& operator<< (ostream& cout,const Mystring& s)
{
cout<<"\""<<s.m_Str<<"\""<<"长度为"<<s.Str_len;
return cout;
}
istream& operator>> (istream& cin,Mystring& s)
{
if(s.m_Str!=NULL)
{
delete []s.m_Str;
s.m_Str = NULL;
}
char temp[1024];
cin>>temp;
s.m_Str = new char[strlen(temp)+1];
strcpy(s.m_Str,temp);
s.Str_len = strlen(temp)+1;
return cin;
}
Mystring Mystring::operator+ (const char* str)
{
int newsize = strlen(str)+this->Str_len;
char* temp = new char[newsize];
strcat(temp,this->m_Str);
strcat(temp,str);
Mystring s = temp;
delete []temp;
return s;
}
Mystring Mystring::operator+ (const Mystring& str)
{
int newsize = str.Str_len + this->Str_len-1;
char* temp = new char[newsize];
strcat(temp,this->m_Str);
strcat(temp,str.m_Str);
Mystring s = temp;
delete []temp;
return s;
}
Mystring& Mystring::operator= (const Mystring& s)
{
if(this->m_Str != NULL)
{
delete []this->m_Str;
this->m_Str = NULL;
}
this->m_Str = new char[s.Str_len];
strcpy(this->m_Str,s.m_Str);
this->Str_len = s.Str_len;
return *this;
}
Mystring& Mystring::operator= (const char* str)
{
if(this->m_Str != NULL)
{
delete []this->m_Str;
this->m_Str = NULL;
}
this->m_Str = new char[strlen(str)+1];
strcpy(this->m_Str,str);
this->Str_len = strlen(str)+1;
return *this;
}
bool Mystring::operator!= (const Mystring& str)
{
int i=0;
while(this->m_Str[i]!='\0'&&str.m_Str[i]!='\0')
{
if(this->m_Str[i]!=str.m_Str[i])
{
break;
}
i++;
}
if(this->m_Str[i]==str.m_Str[i])
{
return false;
}
else
{
return true;
}
}
bool Mystring::operator== (const Mystring& str)
{
int i=0;
while(this->m_Str[i]!='\0'&&str.m_Str[i]!='\0')
{
if(this->m_Str[i]!=str.m_Str[i])
{
break;
}
i++;
}
if(this->m_Str[i]==str.m_Str[i])
{
return true;
}
else
{
return false;
}
}
void test_01()
{
Mystring str1("hello");
cout<<str1<<endl;
str1 = "abc";
cout<<str1<<endl;
Mystring str2 = str1;
cout<<str2<<endl;
Mystring str3 = str1 + str2;
cout<<str3<<endl;
if(str1==str2)
{
cout<<"=="<<endl;
}
else
{
cout<<"!="<<endl;
}
if(str1!=str2)
{
cout<<"!="<<endl;
}
else
{
cout<<"=="<<endl;
}
cin>>str1;
cout<<str1<<endl;
cout<<str1[0]<<endl;
str1[0] = 'w';
cout<<str1<<endl;
}
int main(int argc, char* argv[])
{
test_01();
return 0;
}
今天代码量有点多 但是坚持就是胜利 自己可以把这些重载运算符完成 就离天下无敌不远了(ง •_•)ง