先看看系统自带的递增运算符++
// 递增运算符重载 ++; a++; ++a
int a = 10;
cout << ++a << endl; // 11 先加,后输出。
cout << a << endl; // 11 已加。
int b = 10;
cout << b++ << endl; // 10 先输出,然后再加。
cout << b << endl; // 11 已加。
我们定义我们自己的整型。满足前置递增,后置递增。
class MyInt
{
public:
MyInt()
{
m_Num = 0;
}
private:
int m_Num;
};
调用一下试试:
左移运算符报错,说没有匹配的类型。所以我们需要重载,包括使用++也会报错。
所以自己的类型,必须重新定义个运算符重载。
为了使得我们的cout在左侧,所以只能定义一个全局的重载运算符函数。
ostream& operator<<(ostream& cout, MyInt myint)
{
cout << myint.m_Num;
return cout;
}
同时在类内将全局函数声明为友元。
friend ostream& operator<<(ostream& cout, MyInt myint);
此时:调用时,左移不再报错。可以cout输出,至于++仍需要重载。
递增运算符++有两种:前置,后置;
1、前置递增++运算符
MyInt& operator++()
{
m_Num++; // 前置:先加,后返回。
return *this;
}
前置递增:先加,然后返回,返回的是本体的值。所以要接收本体值。解引用this,同时返回值具有链式,所以,是返回本体值的引用。因此:return *this;返回的是调用者本身:MyInt&。
this是指向自身的,把自身解引用。返回的是本身:因此返回值类型也是MyInt类型的引用。
问题:为何返回本身之后,还要返回引用:返回MyInt类型的值可以吗?
答:返回值满足前置需求,但是因为链式。如果不加,重载函数返回的是:一个新的对象,这个对象不是原来的对象,因此链式加一,并没有加到原来的值上。
返回引用是为了一直对一个数据对象操作加一。
查看调用情况:
成功了。 我们再看后置递增。
2、后置递增++运算符
我们现在类内,尝试写个架子(框架:不知道返回值先写一个void,函数名知道operator++(){}):
报错:无法重载仅按返回类型区分的函数。返回类型不是函数签名,不是区分函数重载的条件。
重载的条件:
- 同一作用域下。
- 函数名相同。
- 参数不同:类型、个数、顺序。不同即可。
那么在C++中,这种情况咋办呢?在参数列表中加上一个(int)
加上一个int之后,可以认为:这是一个++运算符的重载。
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
这个int代表的是一个占位参数,可以用于区分:前置和后置。 写上之后,编译器自己就能区分了,这是一个占位符,表示这边需要输入一个int类型。参数类型不同的重载。
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
而且这个地方必须写int,写double和float都不好使。
比如我们想写一个我们自己的类型。MyInt。不行。
区分前置和后置:用占位参数:int。记住。
继续往下走,后置递增:先返回本体;然后再++。
但是有个问题:返回return之后的代码都将无效。
因此需要有个变量temp先临时记忆一下当前的值,存储这个返回值,然后让这个值加一后,最后再把临时记录存储值的变量temp返回。
// 重载后置递增。
MyInt operator++(int) // int 代表占位参数。占位参 数可以区分前置和后置递增。
{
MyInt temp = *this;
m_Num++;
return temp;
}
此处要非常注意:我们返回的是值,而不是引用了。
因为,如果我们如果返回的是引用,相当于返回的是临时的局部变量temp。这个局部变量temp保存在栈中,在当前函数执行完之后,就立即销毁了,内存释放,后面如果还要返回,还要继续调用,那么就是非法操作。所以后置递增一定要返回值。
前置递增返回的是引用;后置递增返回的是值。
递增运算符重载全部代码:
#include<iostream>
using namespace std;
class MyInt
{
friend ostream& operator<<(ostream& cout, MyInt myint);
public:
MyInt()
{
m_Num = 0;
}
// 递增有两种:前置递增和后置递增。同时具有链式。
// 重载前置递增。
MyInt& operator++()
{
m_Num++; // 前置:先加,后返回。
return *this;
}
// 重载后置递增。
MyInt operator++(int) // int 代表占位参数。占位参 数可以区分前置和后置递增。
{
MyInt temp = *this;
m_Num++;
return temp;
}
private:
int m_Num;
};
ostream& operator<<(ostream& cout, MyInt myint)
{
cout << myint.m_Num;
return cout;
}
void test01()
{
MyInt myint;
cout << myint << endl;
myint++;
}
void test02()
{
MyInt myint;
cout << myint++ << endl;
cout << myint << endl;
}
//虽是一元,但是链式编程。
int main()
{
// 递增运算符重载 ++; a++; ++a
int a = 10;
cout << ++a << endl; // 11 先加,后输出。
cout << a << endl; // 11 已加。
int b = 10;
cout << b++ << endl; // 10 先输出,然后再加。
cout << b << endl; // 11 已加。
int c = 10;
cout << ++++c << endl;
cout << c << endl;
test02();
system("pause");
return 0;
}