上回发的帖子里讲了为什么要用常引用作形参【C++基础】常量引用、指针常量与常量指针 ; 顶层const与底层const
今天又遇到常量引用作形参的一个例子,在学习黑马视频的重载++运算符时,有一个错误。它的重载左移运算符<<的第二个形参为普通引用MyInteger& p
ostream& operator<<(ostream &cout, MyInteger& p)
{
cout << p.m_Num << endl;
return cout;
}
而重载后置++运算符的函数,因为返回值是变量,如下
MyInteger operator++(int)
{
MyInteger temp = *this;
m_Num++;
return temp;
}
导致调用函数时
void test02()
{
MyInteger myint;
cout << myint++ << endl;
cout << myint << endl;
}
因为myint++是调用后置operator++函数的返回值,该函数返回的是变量值,不是引用,而左移运算符<<重载函数的第二形参是引用类型,所以这里的<<会报错!
当然,可以把<<函数的第二个形参改为MyInteger p
,这样就不会报错,但是前置++重载调用那块报错,因为前置++重载函数返回的是引用类型:
MyInteger& operator++()
{
//先进行++运算
m_Num++;
//再返回自身
return *this;
}
如下,++(++myint)是引用类型,他作为左移运算符<<重载函数的实参与MyInteger p
类型不匹配,应为MyInteger& p
void test01()
{
MyInteger myint;
cout << ++(++myint) << endl;
cout << myint << endl;
}
那这样就陷入矛盾,只能取其一吗,其实不然。我们可以把第二个形参设置为常量引用,即const MyInteger& p
ostream& operator<<(ostream &cout, const MyInteger& p)
{
cout << p.m_Num << endl;
return cout;
}
上篇帖子写过,const int&
可以绑定到普通int上,所以我们把普通常量作为实参,传入常量引用作为形参的函数,也不会出错,这就是上篇帖子说的
非常量 可以转成 常量
由此可见,常量引用作为形参,比普通引用作形参,能接受更多的实参类型,上篇帖子的“hello world”也是一个例子。
完整代码如下
#include
using namespace std;
class MyInteger
{
friend ostream& operator<<(ostream &cout, const MyInteger& p);
public:
MyInteger()
{
m_Num = 0;
}
//重载前置++运算符, 返回引用是为了一直对一个数据进行递增操作
MyInteger& operator++()
{
//先进行++运算
m_Num++;
//再返回自身
return *this;
}
//重载后置++运算符
//int代表占位参数,可以区分前置和后置递增,没有int会认为是重载上面的函数,而仅仅返回值不同又不能重载
MyInteger operator++(int)
{
//后置递增,先做表达式运算再让变量自加1
//先 记录当时结果
MyInteger temp = *this;
//后 递增
m_Num++;
//最后将记录的结果做返回操作
return temp;
}
//后置递增是返回值,前置是返回引用。因为后置递增里temp是局部变量,函数调用完就销毁掉了,后面再引用就是非法操作
private:
int m_Num;
};
//第二个形参改成常量引用
ostream& operator<<(ostream &cout, const MyInteger& p)
{
cout << p.m_Num << endl;
return cout;
}
void test01()
{
MyInteger myint;
cout << ++(++myint) << endl;
cout << myint << endl;
}
void test02()
{
MyInteger myint;
cout << myint++ << endl;
cout << myint << endl;
}
int main()
{
test01();
test02();
return 0;
}