本文将使用计数器类作为案例,详细讲解如何通过转换函数和运算符函数让类的对象能够像内置类型一样直接使用。
现在我们有一个基础版本的计数器如下:
版本1:基础计数器类
#include <iostream>
class Counter {
unsigned cnt = 0;
public:
// 基础功能
void increment() { if (cnt < UINT_MAX) cnt++; }
void decrement() { if (cnt > 0) cnt--; }
unsigned value() const { return cnt; }
};
// 使用示例
void demo_v1() {
Counter c;
c.increment();
c.decrement();
std::cout << "计数器值: " << c.value() << "\n"; // 输出: 2
}
1. 转换函数详解
- 什么是转换函数?
- 转换函数允许类对象在需要特定类型时自动转换为该类型。
格式为:
operator target_type() const;
那么,在这个计数器类中,可以这样写:
operator unsigned() const { return cnt; }
也就是说,直接把基础版本中的构造函数中的这行代码进行了替换:
unsigned value() const { return cnt; }
从而,在使用类的时候,每次都需要调用函数 increment,decrement:
Counter c;
c.increment();
c.decrement();
变为了直接使用 c本身:
Counter c;
std::cout << c; // 输出对象,自动转换为unsigned输出
unsigned total = c + 5; // 参与运算,自动转换为unsigned后相加
if (c > 10) { // 自动转换为unsigned后比较
// 参与条件判断
}
2. 运算符函数详解
- 什么是运算符函数?
- 运算符函数允许类对象使用标准运算符(如++, --, !等)。
格式为:
return_type operator op (parameters);
那么,在这个计数器类中,如果想要替代函数 increment,及函数value的返回值,可以这样写:
// 前置递增
Counter& operator++() {
// 实现递增逻辑
if (cnt < UINT_MAX) cnt++;// 返回自身的引用
return *this;
}
// 后置递增
Counter operator++(int) {
Counter temp = *this;// 保存原始值
++(*this);// 调用前置递增
return temp;// 返回原始值
}
也就是替代了原函数中的这些语句,并且使得自增自减更加的精细了:
void increment() { if (cnt < UINT_MAX) cnt++; }
unsigned value() const { return cnt; }
同理,decrement函数也可以这样写。
那么升级后的计数器类是这样的:
版本2:支持直接调用的计数器类
#include <iostream>
#include <climits>
class Counter {
unsigned cnt = 0;
public:
// 转换函数:Counter -> unsigned
operator unsigned() const { return cnt; }
// 运算符函数:逻辑非
bool operator!() const { return cnt == 0; }//在这里判断输入的cnt是否为0,如果为0,则不执行const函数。
// 运算符函数:前置递增
Counter& operator++() {
if (cnt < UINT_MAX) cnt++;
return *this;
}
// 运算符函数:后置递增
Counter operator++(int) {
Counter temp = *this;
++(*this);
return temp;
}
// 运算符函数:前置递减
Counter& operator--() {
if (cnt > 0) cnt--;
return *this;
}
// 运算符函数:后置递减
Counter operator--(int) {
Counter temp = *this;
--(*this);
return temp;
}
};
// 使用示例
void demo_v2() {
Counter c;
// 直接使用递增运算符
++c; // 前置递增
c++; // 后置递增
// 直接输出对象(调用转换函数)
std::cout << "计数器值: " << c << "\n"; // 输出: 2
// 直接参与运算(调用转换函数)
unsigned total = c * 10;
std::cout << "总数值: " << total << "\n"; // 输出: 20
// 使用逻辑非运算符
if (!c) {
std::cout << "计数器为零\n";
} else {
std::cout << "计数器不为零\n"; // 输出此项
}
}