- C++基本运算符:
只能用于基本数据类型的运算符,无法进行对象间的计算,方便起见引入了运算符重载。
- 重载运算符:
- 就是对已有的运算符进行重定义,赋予其另一种功能,以适应不同的数据类型运算(比如结构体、对象之间的运算)。
- 重载运算符是具有特殊名字的函数,它们的名字由关键字operator和其后面要定义的运算符号共同组成,且重载的运算符函数也包含返回类型,参数列表和函数体。
- 重载运算符写法就是:
返回类型 函数名(重载的运算符) (参数)
- 加号运算符重载:
class Person
{
public:
//构造函数
Person(string name, int age)
{
this->p_name = name;
this->p_age = age;
}
//运算符重载 也可以发生函数重载
//返回类型 函数名 参数类型 引用数据类型
Person operator+ (Person &pSource)
{
Person pNew;
pNew.p_name = "none";
pNew.p_age = this->p_age + pSource.p_age;
return pNew;
}
//全局函数重载:
//Person operator+ (Person &p1, Person &p2);
private:
string p_name;
int p_age;
};
void text1()
{
Person zhang("sige", 18);
Person gu("shuai", 22);
//第一种写法:函数调用
//Person d = zhang.operator+(gu);
//第二种写法:简化写法
Person d = zhang + gu;
}
像上面这样子实现时,进行对象之间的加法,实际就是调用了对象内的运算符重载函数。
- 左移运算符重载:
//标准输出流 函数名 标准输出流 需要操作的对象
ostream& operator<<(ostream &cout, Person &p)
- 这里的左移运算符的重载目的是 实现直接输出对象中的数据内容
class Person
{
//友元,使类外函数可以访问本类内所有内容
friend ostream& operator<<(ostream &cout, Person &p);
public:
Person(string name, int age)
{
this->p_name = name;
this->p_age = age;
}
private:
string p_name;
int p_age;
};
ostream& operator<<(ostream &cout, Person &p)
{
cout << "m_name = " << p.p_name << " p_age = " << p.p_age;
return cout;
}
void text2()
{
Person zhang("sige", 18);
cout << zhang << endl;
}
- 注意:
- cout的数据类型是ostream(标准输出流),这里想要实现左移运算符在对象之前的重载操作,就需要将cout作为参数传入函数中;同时该函数不能是类的成员函数,需要作为全局函数来实现(我是这么理解的)
- 最后返回cout是将标准输出流返回,目的是实现调用时的链式访问。
- 同时类外的函数要方位类内的私有内容,可以使用友元的方式来给他操作权限
- 递增运算符重载(递减同理)
class Table1
{
friend ostream & operator<<(ostream& cout, Table1& p);
public:
Table1()
{
tAge = 18;
}
//前置递增
Table1& operator++()
{
tAge++;
return *this;
}
//后置递增
Table1 operator++(int)
{
Table1 temp = *this;
this->tAge++;
return temp;
}
private:
int tAge;
};
//这个是打印函数(重载运算符)
ostream & operator<<(ostream& cout, Table1& p)
{
cout << "tAge = " << p.tAge << endl;
return cout;
}
void test1()
{
//重载++
Table1 p1(10);
//测试
cout << ++p1 << endl;
cout << p1++ << endl;
cout << p1 << endl;
}
- 注意:
- 递增运算符实现时应分为前置递增和后置递增两种
- 前置递增的实现是先进行自增运算,再将结果返回
- 后置递增的实现是储存递增前的对象,将结果递增后,返回之前存储的对象
- 前置递增返回值是自身,后置递增返回的值是一个新的对象(通过拷贝构造函数)。
- 重载赋值运算符:
class Table2
{
friend ostream & operator<<(ostream& cout, Table2& p);
public:
//构造
Table2(int length)
{
tAge = 18;
this->length = new int(length);
}
//赋值运算符重载
Table2& operator=(Table2 &p)
{
this->tAge = p.tAge;
if (this->length != nullptr)
{
delete this->length;
this->length = nullptr;
}
this->length = new int(*(p.length));
return *this;
}
~Table2()
{
if (length != nullptr)
{
delete length;
}
}
private:
int tAge;
int* length;
};
//打印输出函数
ostream & operator<<(ostream& cout, Table2& p)
{
cout << "tAge = " << p.tAge << " length = " << *(p.length);
return cout;
}
void test2()
{
//重载 =
Table2 p1(10);
Table2 p2(20); //必须先初始化,否则野指针
p2 = p1;
cout << p2 << endl;
}
- 注意:
- 当类内存在堆区开辟的内存空间,在赋值时需要先保证之前的空间已被释放;且拷贝堆区空间数据时,必须重新开辟空间,以保证析构时不会重复释放内存(类似与拷贝构造函数)。
- 重载== 和 !=运算符
class Table2
{
friend ostream & operator<<(ostream& cout, Table2& p);
public:
Table2(int length)
{
tAge = 18;
this->length = new int(length);
}
bool operator==(Table2& p)
{
if (this->tAge == p.tAge &&
*this->length == *p.length)
{
return true;
}
else
{
return false;
}
}
bool operator!=(Table2& p)
{
if (this->tAge != p.tAge ||
*this->length != *p.length)
{
return true;
}
else
{
return false;
}
}
~Table2()
{
if (length != nullptr)
{
delete length;
}
}
private:
int tAge;
int* length;
};
ostream & operator<<(ostream& cout, Table2& p)
{
cout << "tAge = " << p.tAge << " length = " << *(p.length);
return cout;
}
void test3()
{
//重载 == !=
Table2 p1(10);
Table2 p2(20); //必须先初始化,否则野指针
if (p1 == p2)
{
cout << "p1 == p2" << endl;
}
if (p1 != p2)
{
cout << "p1 != p2" << endl;
}
}
这个没啥好注意的,比较简单,就是简单的比较操作。
- 重载()仿函数
- 目的是实现一种简写的方法
class MyPrint
{
public:
int operator()(string text, int num1, int num2)
{
cout << text << endl;
return num1 + num2;
}
};
void test4()
{
//重载() 仿函数
MyPrint a;
a.operator()("我爱大又白", 1, 1);
//这里在函数内打印text文本
//这里是该函数的简化调用方式
cout << a("我爱嗨丝", 2, 18) << endl;
//这里在函数内打印文本,且在函数外打印函数返回值
//匿名函数对象调用
cout << MyPrint()("asas", 1, 2) << endl;
}