[] 和 () 运算符重载
本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 45 课,共 104 课。
下标运算符([])可以让你的类像数组一样运行,从而通过索引访问元素。函数调用运算符(())可以让对象变成可调用的实体,这种对象称为函数对象。
下面是一个带有下标运算符的简单数组包装器:
class IntArray {
int* data;
size_t size;
public:
IntArray(size_t s) : size(s), data(new int[s]()) {}
~IntArray() { delete[] data; }
int& operator[](size_t index) {
return data[index];
}
const int& operator[](size_t index) const {
return data[index];
}
};注意,我们提供了两个版本:一个返回非 const 引用(允许修改),const 版本则适用于 const 对象。这样你就可以使用 arr[0] = 5; 进行读取和写入。
函数调用运算符可以创建像函数一样被“调用”的对象:
class Multiplier {
int factor;
public:
Multiplier(int f) : factor(f) {}
int operator()(int value) const {
return value * factor;
}
};
Multiplier triple(3);
int result = triple(10); // 返回 30函子很强大,因为它们可以在多次调用之间保持状态,这一点与普通函数不同。它们常用于 STL 算法中,适合需要记住配置值的可定制行为。
挑战
简单我们来创建一个 ScoreTracker 类,将下标运算符和函数调用运算符结合起来。这个类会存储玩家的分数,让你可以使用 [] 按索引访问分数,同时它也会充当一个函数对象,对传入的分数应用奖励倍数。
你需要创建两个文件来组织代码:
ScoreTracker.h:定义一个ScoreTracker类,用于管理玩家分数数组并应用奖励。你的类应包含:- 一个动态分配的
int*数组,用于存储分数 - 一个
size_t成员,用于记录分数的数量 - 一个
double成员,用于记录奖励倍数 - 一个接收大小和奖励倍数的构造函数,并将所有分数初始化为 0
- 一个能正确清理动态内存的析构函数
- 下标运算符
[](包括 const 和非 const 版本),用于按索引访问分数 - 函数调用运算符
(),接收一个int类型的分数,并返回该分数乘以奖励倍数后的结果(类型为int) - 一个
getSize()方法,用于返回分数的数量
非 const 下标运算符会返回引用,因此你可以这样写:
tracker[0] = 100;。const 版本允许对 const 对象进行只读访问。函数调用运算符应标记为const,因为它不会修改对象的状态。- 一个动态分配的
main.cpp:读取以下输入(每项各占一行):- 玩家数量(大小)
- 奖励倍数(类型为 double)
- 每位玩家的分数(每行一个,数量与玩家数量相同)
- 一个用于应用奖励的测试分数
创建一个
ScoreTracker,使用下标运算符存储每位玩家的分数,然后显示所有分数。最后,使用函数调用运算符计算应用奖励后的分数。输出格式:
Player 0: <score> Player 1: <score> ... Bonus applied to <test_score>: <result>
例如,玩家数量为 3,奖励倍数为 1.5,分数分别为 100、200、150,测试分数为 80:
Player 0: 100
Player 1: 200
Player 2: 150
Bonus applied to 80: 120使用 std::stoi() 和 std::stod() 转换输入。别忘了在头文件中添加头文件保护。
亲手试试
#include <iostream>
#include <string>
#include "ScoreTracker.h"
using namespace std;
// TODO: 实现 ScoreTracker 构造函数
ScoreTracker::ScoreTracker(size_t size, double multiplier) {
// TODO: 初始化成员并分配动态数组
// 将所有分数初始化为 0
}
// TODO: 实现 ScoreTracker 析构函数
ScoreTracker::~ScoreTracker() {
// TODO: 释放动态内存
}
// TODO: 实现非 const 下标运算符
// TODO: 实现 const 下标运算符
// TODO: 实现函数调用运算符
// TODO: 实现 getSize 方法
size_t ScoreTracker::getSize() const {
// TODO: 返回分数的数量
}
int main() {
string line;
// 读取玩家数量
getline(cin, line);
size_t numPlayers = stoi(line);
// 读取奖励倍数
getline(cin, line);
double multiplier = stod(line);
// TODO: 使用 numPlayers 和 multiplier 创建 ScoreTracker
// TODO: 读取每位玩家的分数,并用下标运算符存储
// TODO: 读取测试分数
// TODO: 按以下格式显示所有玩家的分数:"Player X: <score>"
// TODO: 按以下格式显示应用奖励后的结果:"Bonus applied to <test_score>: <result>"
return 0;
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C++ 在线编译器