文章目录
- 运算符重载:
- 1.1 = 运算符重载
- 1.2 + 运算符重载
- 1.3 && 运算符
- 1.4 << 运算符(输出运算符)
- 1.5 ++运算符
- 前置 ++(仅对实部++)
- 后置++(仅对实部++)
- 函数的返回值为解引用?
运算符重载:
原因:为了增强程序的可读性,引入运算符重载。目的就是为了让自定义的类型能够像内置类型一样可以直接使用运算符计算。换可以使用C++中的运算符操作对象。
语法:返回值类型 operator 运算符 (形参列表)
1.1 = 运算符重载
当使用一个已存在的对象,给另外一个已存在的对象赋值的时候自动调动的成员方法。
如果没有实现,会自动生成一个浅拷贝的等号运算符重载。
person &operator=(const person& src)
{
//防止自赋值
if (this !=&src)
{
//防止内存泄漏
delete[] _name;//将被赋值的_name中的内存释放,重新申请。
//防止浅拷贝
_name = new char(strlen(src._name) + 1);
memset(_name, 0, strlen(src._name)+1);
for (int i = 0; i < strlen(src._name); i++)
{
_name[i] = src._name[i];
}
_sex = src._sex;
_age = src._age;
}
return *this;
//打印一些说明调用了此函数
cout << "void operator=(const person &src)" << endl;
}
int main(void)
{
char name[] = "baiU";
person p1(name,1, 22);
person p2;
p2 = p1;
//等同于:p2.operator=(p1);
p2.show();
return 0;
}
运行结果:
结果显示:
首先构造p1,接下来构造p2,在调用赋值运算符重载。析构p2,在析构p1。
注意:
1.防止自赋值
2.防止内存泄漏
3.防止浅拷贝
如果成员属性中有指针。就绪要额外申请空间。防止浅拷贝。
1.2 + 运算符重载
- 返回类型为类的类型
- this指针声明为const
- 第二加数声明为const
Complex operator+(const Complex &cx)const
Complex operator+(const Complex &cx)const
{
//int a = Real + cx.Real;
//int b = Image+cx.Image;
//调用了拷贝构造函数,将this和cx的和传给tmp
Complex tmp(Real + cx.Real,Image+cx.Image);
//return Complex(Real + cx.Real,Image+cx.Image); //不需要调用拷贝构造函数,直接创建一个临时对象,将值写入到临时对象空间
return tmp; //创建了一个临时对象,只析构一次
}
Complex p1(5, 6);
Complex p2(7, 8);
Complex p3 = p1 + p2;
// Complex p4 = p1.operator+(p2);
1.3 && 运算符
比如要比较两个复数的实部是否等于0
bool operator &&(const Complex& cx)const
{
return Real && cx.Real;
}
1.4 << 运算符(输出运算符)
把cout当做cout当做参数穿进去
使用特定的 ostream
//简易版本,只能当做show方法一样使用
/* void operator<<(ostream& out)
{
out << Real << "+" << Image << "i" << endl;
}
*/
无法使用cout直接输出
改进:将函数的返回值类型改为输出流对象,即ostream
friend ostream& operator<<(ostream& out, const Complex& cx);
};
ostream &operator<<(ostream& out, const Complex& cx)
{
out << cx.Real << "+" << cx.Image << "i" << endl;
return out;
}
一次输出两个对象
cout << p1<<p2 ;
1.5 ++运算符
前置 ++(仅对实部++)
前置++就是先+1,再返回
实现:只针对复数的实部
- 引用的方式返回函数的值,不能是局部变量,或局部对象
- 返回的是this指针的本身。
用引用作函数的返回值的最大的好处是在内存中不产生返回值的副本。
Complex& operator++()
{
++Real;
return *this;
}
后置++(仅对实部++)
先传值,再自增。
就是先把值给一个临时量。
Complex operator++(int)
{
int tmp = Real;
++Real;
return Complex(tmp,Image);
}
函数的返回值为解引用?
- 当函数运算符重载返回的是对象时,会在连续赋值运算过程中,调用两次拷贝构造函数和析构函数,(return 创建一个新对象),而如果采用 引用的方式返回,就不需要在创建对象,因为return的就是已经存在的对象的引用(别名)。
- 用引用作函数的返回值的最大的好处是在内存中不产生返回值的副本
- 允许连续赋值
#include<iostream>
#include<string.h>
using namespace std;
class String
{
private:
char* str;
int len;
public:
String(const char* s);//构造函数声明
String &operator=(const String& another);//运算符重载,此时返回的是对象
void show()
{
cout << "value = " << str << endl;
}
/*copy construct*/
String(const String& other)
{
len = other.len;
str = new char[len + 1];
strcpy_s(str, len+1,other.str);
cout << "copy construct" << endl;
}
~String()
{
delete[] str;
cout << "deconstruct" << endl;
}
};
String::String(const char* s)//构造函数定义
{
len = strlen(s);
str = new char[len + 1];
strcpy_s(str,len+1, s);
}
String String::operator=(const String& other)//运算符重载
{
if (this == &other)
return *this;
// return;
delete[] str;
len = other.len;
str = new char[len + 1];
strcpy_s(str,len+1, other.str);
return *this;
// return;
}
int main()
{
String str1("abc");
String str2("123");
String str3("456");
str3 = str1 = str2;//str3.operator=(str1.operator=(str2))
str3.show();
str1.show();
return 0;
}
如果以解引用的方式返回:
String &String::operator=(const String& other)//运算符重载
{
if (this == &other)
return *this;
// return;
delete[] str;
len = other.len;
str = new char[len + 1];
strcpy_s(str,len+1, other.str);
return *this;
// return;
}
str3 = str1 = str2;//str3.operator=(str1.operator=(str2))
少执行了两次拷贝构造函数,因为返回的都是this的别名,因此是对str进行了修改买就可以完成连续赋值。