文章目录
4.5.3 自增(递增)运算符重载
作用:通过重载递增运算符,实现自己的整型数据
项目需求
普通的自增运算符有如下案例:
int a = 0;
cout << ++a << endl; // 1
cout << a << endl; // 1
int b = 0;
cout << b++ << endl; // 0
cout << b << endl; // 1
项目需求:实现一个自定义的整形类型MyInteger,并且同样实现上述代码的效果:
MyInteger myInt1 = 0;
cout << ++myInt1 << endl; // 1
cout << myInt1 << endl; // 1
MyInteger myInt2 = 0;
cout << myInt2++ << endl; // 0
cout << myInt2 << endl; // 1
由此可以知道我们如果要实现这个项目,需要有如下步骤:
- 自定义一个类型:
MyInteger,以仿照int类型 - 完成
MyInteger类型的<<运算符重载 - 完成
MyInteger类型的++运算符重载(分为前置++和后置++的实现)
项目实现
定义MyInteger类
class MyInteger
{
public:
/// <summary>
/// MyInteger类的无参构造:定义MyInteger类型的变量(对象)且无赋初值的情况下,
/// (默认)使得其属性value值为0
/// </summary>
MyInteger()
{
value = 0;
}
/// <summary>
/// MyInteger类的有参构造:定义MyInteger类型的变量(对象)且同时赋初值的情况下,
/// 使用该初值for_value作为其属性value的值
/// </summary>
/// <param name="for_value">
/// :MyInteger类型的变量(对象)定义的同时要赋值给value的初值
/// </param>
MyInteger(int for_value)
{
this->value = for_value;
}
private:
int value;
};
以上代码是在我程序中的实际编写情况,为了让我们对代码一目了然,我去掉了一些注释,留下必要的解释,参考代码如下:
class MyInterger
{
public:
MyInterger() // 无参构造:为了确保后续我们程序中定义MyInteger类型的变量(对象)且无赋初值的情况下,
{
//(默认)使得其属性value为0
value = 0;
}
MyInteger(int for_value)// 有参构造:在程序中定义该变量(对象)且同时赋初值的情况下,
{
// 使用该初值for_value作为其属性value的值
this->value = for_value;
}
private:
int value; // 存储变量(对象)值
};
定义完MyInteger类之后,我们对自定义的MyInteger类进行测试,以检验我们对这个自定义的类能否仿照案例中定义int a = 0和int b = 0一样进行变量(对象)的定义:
void test02()
{
MyInteger myInt; // 无赋初值定义MyInteger类型变量myInt
MyInteger myInt1 = 0; // 赋初值定义MyInteger类型变量myInt1
MyInteger myInt2 = 0; // 赋初值定义MyInteger类型变量myInt2
}
编译器编译效果如下:
编译器没有报错。
说明我们MyInteger类的定义是OK的!但是可能大家这里会有一个问题或者说是一个猜测和思考
小思考:仿照int中的"先定义,后赋值"
既然我们现在这个MyInteger可以仿照int定义的同时不赋初值的变量,也可以仿照int定义的同时有赋初值的变量,那能不能仿照int"先定义,后赋值"的这种情况呢?
这里我做了一下尝试,代码如下:
void test02()
{
MyInteger myInt; // 先定义
myInt = 10; // 后赋值
cout << myInt.value << endl; // 打印输出,以验证是否真正赋值成功
}
(为了上述代码中的第5行能够访问myInt中的value,我们先把MyInteger中对value的访问权限由private改为public,此处就不作代码展示了,该问题验证完之后我会将权限修改回private)
程序运行效果如下:
程序运行后的确输出了赋值的10…一切看起来都好像挺合理,但要执着追求事物本质的我们怎么可能这么容易就罢休呢?
我们对上面这三行代码的思考的逻辑是这样的:
如果真的是赋值成功,那么这三行代码就应该自始至终都只有一个
MyInteger类型的变量myInt存在,也就是说MyInteger的构造函数只调用了一次;否则,如果
MyInteger的构造函数调用了两次及以上就是说明上面三行代码不是一个简单的赋值过程
为了验证我们的这个猜想,我对MyInteger类中的构造函数作了一些该进,改进后的MyInteger类定义如下:
class MyInteger
{
public:
MyInteger()
{
cout << "无参构造调用" << endl; // 无参构造调用提示
value = 0;
}
MyInteger(int for_value)
{
cout << "有参构造调用" << endl; // 有参构造调用提示
this->value = for_value;
}
public:
int value;
};
此时再运行程序,结果如下:
发现实际上构造函数总共调用了两次,实际上test02()中第二行代码myInt = 10;的本质应该是这样的:
myInt = MyInteger(10);
同理第一行代码的本质是:
myInt = MyInteger();
(这里对本质的分析应用的是C++中创建对象时三种方法中的"隐式转换法"的知识)
所以test02()也可以这样写:
void test02()
{
MyInteger myInt = MyInteger(); // 先定义
myInt = MyInteger(

本文介绍了如何在C++中为自定义类型MyInteger实现自增运算符重载,包括前置++和后置++。首先,通过类定义和构造函数创建MyInteger对象,然后通过重载<<运算符解决输出问题。接着,通过成员函数和全局函数两种方式实现前置++运算符,确保返回类型为MyInteger引用。最后,通过拷贝对象实现后置++运算符,返回自增前的对象副本。文章还探讨了前后置++运算符在链式操作中的区别,并指出后置++无法支持链式操作。



最低0.47元/天 解锁文章
2202





