加号运算符重载
class Person
{
public:
int mem_a;
int mem_b;
//1、通过成员函数重载+号
/*
#include<iostream>
using namespace std;
class Person
{
public:
int mem_a;
int mem_b;
//1、通过成员函数重载+号
/*
Person operator +(Person &p)
{
Person sum;
sum.mem_a = this->mem_a + p.mem_a;
sum.mem_b = this->mem_b + p.mem_b;
return sum;
//返回类型不能是引用,因为不能返回局部变量的引用
}
调用形式
Person p3 = p1.operator+(p2);
或者 p3 = p1 + p2;
*/
};
Person operator +(Person &p1,Person &p2)
{
Person sum;
sum.mem_a = p1.mem_a + p2.mem_a;
sum.mem_b = p1.mem_b + p2.mem_b;
return sum;
}
int main(){
Person p1;
p1.mem_a = 10;
p1.mem_b = 10;
Person p2;
p2.mem_a = 10;
p2.mem_b = 10;
Person p3;
p3 = p1 + p2;
cout<<p3.mem_a<<p3.mem_b;
return 0;
}
一般情况下,我们把算术运算符定义成非成员函数,因为我们不需要改变运算对象的状态,所以形参都是常量的引用。
重载输出运算符
- 重载输出运算符函数不能是成员函数,因为不能实现<<在左边。 例如 p<<cout 是不可行的。
- 通常情况下,输出运算符的第一个形参是一个非常量ostream对象的引用。它是非常量是因为向流写入内容会改变其状态;而该对象是引用是因为我们不能直接复制一个ostream对象。
- 第二个形参一般是一个常量(想打印的类类型)的引用。是引用的原因是为了避免复制实参;而之所以形参可以是常量是因为打印内容一般不会改变对象的内容。
- operator<<返回类型一般要返回它的ostream引用(如果返回类型是void的话,cout<<x<<endl中第二个<<就会无效。)
#include<iostream>
using namespace std;
class Person
{
public:
Person() = default;
Person(int a,int b)
{
this->mem_a = a;
this->mem_b = b;
}
friend ostream &operator<<(ostream &os,const Person &p);
private:
int mem_a;
int mem_b;
};
ostream &operator<<(ostream &os,const Person &p)
{
os << "a: "<<p.mem_a <<" b: "<<p.mem_b;
return os;
}
int main(){
Person p1(10,10);
cout << p1 << endl;
return 0;
}
一般输出运算符与友元搭配可实现自定义数据类型。
输出运算符应该主要负责打印对象的内容而非控制格式,输出运算符不应该打印换行符。
前置/后置 递增递减运算符
#include<iostream>
using namespace std;
class Myclock
{
public:
Myclock()
{
this->second = 0;
}
friend ostream &operator<<(ostream &os,const Myclock &c);
Myclock& operator++();
Myclock operator++(int);
Myclock& operator--();
Myclock operator--(int);
private:
int second;
};
Myclock& Myclock::operator++() //为了跟内置版本保持一致,前置运算符应该返回递增或递减后对象的引用。
{
++second;
return *this;
}
Myclock Myclock::operator++(int)
{
Myclock clock = *this;
++this->second;
return clock;
}
Myclock& Myclock::operator--() //为了跟内置版本保持一致,前置运算符应该返回递增或递减后对象的引用。
{
--second;
return *this;
}
Myclock Myclock::operator--(int) //为了跟内置版本保持一致,前置运算符应该返回递增或递减后对象的引用。
{
Myclock clock = *this;
--this->second;
return clock;
}
ostream &operator<<(ostream &os,const Myclock &c)
{
os << "second: "<<c.second;
return os;
}
int main(){
Myclock p1;
int a = 10,b = 10;
cout<< ++++a << ++++++b << endl;
cout<<p1<<endl;
cout<<p1++<<endl;
cout<<p1<<endl;
cout<<++p1<<endl;
cout<<--p1<<endl;
cout<<p1--<<endl;
return 0;
}
- 最好将递增递减运算符设定为成员函数,因为它们改变的正好是所操作对象的状态。
- 在参数列表里使用int这一占位参数来区分前置、后置递增递减运算符。
- 为了与内置版本保持一致,后置运算符应该返回对象的原值(递增或递减之前的值),返回的是值而不是引用(不能返回局部变量的引用。)
显式地调用后置运算符
Myclock c;
c.operator++(0);//调用后置版本的operator++;
c.operator--(); //调用前置版本的operator++;
重载赋值运算符
- 我们可以重载赋值运算符。不论形参的类型是什么,赋值运算符都必须定义成员函数,并且返回左侧运算对象的引用。
- 当类包含有指针数据成员时,合成赋值运算符函数常会引发“指针悬挂”问题。
#include <iostream>
#include<cstring>
using namespace std;
class String {
char *ptr;
int n;
public:
String(char * s, int a) {
ptr = new char[strlen(s) + 1];
strcpy(ptr, s);
n = a;
}
~String()
{
delete ptr;
}
void print() { cout << ptr << endl; }
String& operator=(const String& s);
};
String& String::operator=(const String& s) {
if (this == &s) return *this;//如果是同一对象/引用 如s1(s1);
delete ptr;//原来的ptr字符串容纳长度可能偏小,所以需要delete
ptr = new char[strlen(s.ptr) + 1];
strcpy(ptr, s.ptr);
n=s.n;
return *this;
}
int main() {
String p1("Hello", 8); //L1
{ String p2("chong qing", 10); //L2
p2 = p1; //L3
cout << "p2:"; //L4
p2.print(); //L5
} //L6
cout << "p1:"; //L7
p1.print(); //L8
}
重载复合赋值运算符
//复合赋值运算符也应该返回左侧运算对象的引用,最好是成员函数
Person& operator+=(const Person &p2)
{
mem_a += p2.mem_a;
mem_b += p2.mem_b;
return *this;
}
关系运算符重载
//在如下给定的代码中,为 MyCircle 类添加关系运算符 >、<、>=、<=、==、!= ,实现按照半径对 MyCircle 对象进行比较。
//类内声明
bool operator >(const MyCircle &m1);
bool operator<(const MyCircle &m1 );
bool operator>=(const MyCircle &m1);
bool operator<=(const MyCircle &m1);
bool operator==(const MyCircle &m1);
bool operator!=(const MyCircle &m1);
bool MyCircle::operator>(const MyCircle &m1)
{
if(this->radius_>m1.radius_)
return true;
else
return false;
}
bool MyCircle::operator<(const MyCircle &m1)
{
if(this->radius_<m1.radius_)
return true;
else
return false;
}
bool MyCircle::operator >=(const MyCircle &m1)
{
if(this->radius_ >= m1.radius_)
return true;
else
return false;
}
bool MyCircle::operator <=(const MyCircle &m1)
{
if(this->radius_ <= m1.radius_)
return true;
else
return false;
}
bool MyCircle::operator ==(const MyCircle &m1)
{
return this->radius_ == m1.radius_;
}
bool MyCircle::operator !=(const MyCircle &m1)
{
return !(this->radius_ == m1.radius_);
}
int main() {
int r1 , r2 , r3 = 0;
cin >> r1 >> r2 >> r3;
MyCircle c1 , c2 , c3;
c1.setRadius(r1);
c2.setRadius(r2);
c3.setRadius(r3);
cout << (c1 > c2) << endl;
cout << (c1 < c2) << endl;
cout << (c2 >= c3) << endl;
cout << (c2 <= c3) << endl;
cout << (c1 == c3) << endl;
cout << (c1 != c3) << endl;
return 0;
}
/* 输出:
0
1
1
0
0
1
*/