原文链接(点击原文链接获取更多学习干货):
Twelve 类运算符重载 – 布尔博客http://blog.bools.cn/archives/1640
1.加号运算符重载
如果想要自定义类型进行加减操作,需要编写函数来进行重载。在成员函数或全局函数中写函数
函数名operator+(){}
1.成员函数的加号重载
class person
{
public:
person() {};
person(int a, int b) :m_A(a), m_B(b)
{};
加号运算符重载,成员函数
person operator+(person& p)
{
person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}
int m_A;
int m_B;
};
void test01()
{
person p1(10, 20);
person p2(20, 30);
person p3 = p1 + p2;
person p4 = p3.operator+(p2);//两个一样的作用,就是将加号重载,类成员函数的加号运算符
cout << "p3是p1和p2加之后:m_A:" << p3.m_A << " m_B:" << p3.m_B << endl;
cout << "p4是p4和p2加之后:m_A:" << p4.m_A << " m_B:" << p4.m_B << endl;
}
成员函数里面的函数加号重载实现方法有两种
person p3 = p1 + p2;
person p4 = p3.operator+(p2);//两个一样的作用,就是将加号重载,类成员函数的加号运算符
直接加减或者使用类里面的函数。
2.全局函数的加号重载
class person
{
public:
person() {};
person(int a, int b) :m_A(a), m_B(b)
{};
int m_A;
int m_B;
};
//利用全局函数来进行加号运算符的重载
person operator+(person& p1, person& p2)
{
person temp;
temp.m_A = p1.m_A + p2.m_A;
temp.m_B = p1.m_B + p2.m_B;
return temp;
}
void test01()
{
person p1(10, 20);
person p2(20, 30);
person p3 = p1 + p2;
person p4 = operator+(p2, p3);//全局函数的加号重载
cout << "p3是p1和p2加之后:m_A:" << p3.m_A << " m_B:" << p3.m_B << endl;
cout << "p4是p4和p2加之后:m_A:" << p4.m_A << " m_B:" << p4.m_B << endl;
}
全局函数的加号重载也可以直接用加号+,也可以像用函数一样
person p3 = p1 + p2;
person p4 = operator+(p2, p3);//全局函数的加号重载
2.左移运算符重载
一般看到的都是普通的左移运算符,常用在cout<<中,而只能识别编译器默认的数据类型,如果想要输出自定义数据类型,就要重载左移运算符。
而和加号重载运算符不一样,左移重载运算符不能写在成员函数里面。
例子:
class person
{
public:
person() {};
person(int a, int b)
{
m_A = a;
m_B = b;
}
int m_A ;
int m_B;
};
ostream& operator<<(ostream& cout, person& p)
{
cout << "m_A:" << p.m_A << " m_B:" << p.m_B;
return cout;
}
void test01()
{
person p1(10,20);
cout << p1 << endl;
}
在例子当中,我们看到,因为cout属于ostream的类似于数据类型当中,所以调用的时候调用参数类型是ostream,而返回值也是ostream类型。
3.前置后置递增运算符重载
前置后置递增运算符和前面两个一样,也是对自定义的运算符的一种重载。
就是像i++或者++i、i--或者--i一样。
前置++
先++,再返回对象。
class MyInteger
{
friend ostream& operator<<(ostream& cout, MyInteger& myint);
public:
MyInteger()
{
m_Num = 0;
};
//前置重载
MyInteger& operator++()
{
//直接++,返回的是对象
this->m_Num++;
return *this;
}
private:
int m_Num;
};
ostream& operator<<(ostream& cout, MyInteger& myint)
{
cout << myint.m_Num;
return cout;
}
void test01()
{
MyInteger myint;
cout << ++myint << endl;
}
前置后置增函数都是成员函数,而因为在输出时cout了自定义的数据类型,所以还要进行一次左移符号重载。
后置++
先保存一个临时值,再++。
class MyInteger
{
friend ostream& operator<<(ostream& cout, MyInteger& myint);
public:
MyInteger()
{
m_Num = 0;
};
//后置重载
MyInteger& operator++(int)
{
//用一个临时变量保存先
MyInteger temp = *this;
m_Num++;
return temp;
}
private:
int m_Num;
};
ostream& operator<<(ostream& cout, MyInteger& myint)
{
cout << myint.m_Num;
return cout;
}
void test01()
{
MyInteger myint;
cout << myint++ << endl;
}
后置函数重载的话需要先将对象的值保存,然后++。
而在使用前置或者后置时,优先考虑使用前置
这里需要注意:返回值用引用的时候返回的是对象,而不用引用的时候返回的只是值而已。
4.指针运算符的重载(智能指针)
智能指针
意思就是将开辟的堆空间的指针,能够释放,避免忘记释放。
class person
{
public:
person(int a)
{
this->m_A = a;
}
void showage()
{
cout << "年龄是:" << this->m_A << endl;
}
private:
int m_A;
};
//智能指针,意思是用来删除开辟的堆空间的
class smartpoint
{
public:
smartpoint(person* person)
{
this->person = person;
}
~smartpoint()
{
if (this->person != NULL)
{
delete this->person;
this->person = NULL;
}
}
private:
person* person;
};
void test01()
{
smartpoint(new person(20));//开辟到堆空间,而类当中能自动释放
}
重点是:
smartpoint(person* person)
{
this->person = person;
}
~smartpoint()
{
if (this->person != NULL)
{
delete this->person;
this->person = NULL;
}
}
将堆空间释放,避免忘记。
->符号重载
class smartpoint
{
public:
person* operator->()
{
return this->person;
}
private:
person* person;
};
void test01()
{
smartpoint sp(new person(20));//开辟到堆空间,而类当中能自动释放
//重载之后,可以直接用person里面的函数。
sp->showage();
}
*符号重载
class smartpoint
{
public:
person& operator*()
{
return *this->person;
}
private:
person* person;
};
void test01()
{
smartpoint sp(new person(20));//开辟到堆空间,而类当中能自动释放
(*sp).showage();
}
5.赋值运算符重载
就是避免堆空间重复删除,也是关于深拷贝和浅拷贝的问题。
class person2
{
public:
void operator=(const person2& p)
{
if (this->p_name != NULL)
{
delete[]this->p_name;
this->p_name = NULL;
}
this->p_name = new char[strlen(p.p_name) + 1];
strcpy(this->p_name, p.p_name);
}
char* p_name;
};