Nạp chồng toán tử [] và ()
Thuộc phần Lập trình hướng đối tượng trong hành trình C++ của Coddy. Bài học 45 trên 104.
Toán tử chỉ số dưới ([]) cho phép lớp của bạn hoạt động như một mảng, giúp truy cập các phần tử theo chỉ số. Toán tử gọi hàm (()) biến đối tượng thành thực thể có thể gọi, được gọi là functor.
Đây là một lớp bọc mảng đơn giản có toán tử chỉ số:
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];
}
};Lưu ý rằng chúng ta cung cấp hai phiên bản: một phiên bản trả về tham chiếu không hằng số (cho phép chỉnh sửa), còn phiên bản hằng số hoạt động với các đối tượng hằng số. Nhờ vậy, bạn có thể viết arr[0] = 5; để đọc và ghi.
Toán tử gọi hàm tạo ra các đối tượng có thể được “gọi” như hàm:
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); // Trả về 30Functor rất mạnh vì chúng có thể duy trì trạng thái giữa các lần gọi, không giống như các hàm thông thường. Chúng thường được dùng với các thuật toán STL khi bạn cần hành vi có thể tùy chỉnh và ghi nhớ các giá trị cấu hình.
Thử thách
DễHãy tạo một lớp ScoreTracker kết hợp cả toán tử chỉ số và toán tử gọi hàm. Lớp này lưu điểm của người chơi và cho phép bạn truy cập điểm theo chỉ số bằng [], đồng thời hoạt động như một đối tượng hàm áp dụng hệ số nhân tiền thưởng cho bất kỳ điểm nào bạn truyền vào.
Bạn sẽ tạo hai tệp để sắp xếp code:
ScoreTracker.h: Định nghĩa lớpScoreTrackerđể quản lý mảng điểm của người chơi và áp dụng tiền thưởng. Lớp của bạn cần có:- Mảng
int*được cấp phát động để lưu điểm - Một thành viên
size_tbiểu thị số lượng điểm - Một thành viên
doublebiểu thị hệ số nhân tiền thưởng - Một hàm khởi tạo nhận kích thước và hệ số nhân tiền thưởng, đồng thời khởi tạo tất cả điểm bằng 0
- Một hàm hủy dọn dẹp bộ nhớ động đúng cách
- Toán tử chỉ số
[](cả phiên bản const và không const) để truy cập điểm theo chỉ số - Toán tử gọi hàm
()nhận một điểmintvà trả về điểm nhân với hệ số nhân tiền thưởng (dưới dạngint) - Một phương thức
getSize()trả về số lượng điểm
Toán tử chỉ số không const trả về một tham chiếu để bạn có thể viết
tracker[0] = 100;. Phiên bản const cho phép chỉ đọc các đối tượng const. Toán tử gọi hàm cần được đánh dấuconstvì nó không thay đổi trạng thái của đối tượng.- Mảng
main.cpp: Đọc các đầu vào sau (mỗi đầu vào trên một dòng riêng):- Số người chơi (kích thước)
- Hệ số nhân tiền thưởng (dưới dạng double)
- Điểm của từng người chơi (mỗi dòng một điểm, số dòng bằng kích thước)
- Một điểm kiểm tra để áp dụng tiền thưởng
Tạo một
ScoreTracker, dùng toán tử chỉ số để lưu điểm của từng người chơi, sau đó hiển thị tất cả điểm. Cuối cùng, dùng toán tử gọi hàm để tính điểm sau khi áp dụng tiền thưởng.Định dạng đầu ra:
Player 0: <score> Player 1: <score> ... Bonus applied to <test_score>: <result>
Ví dụ, với 3 người chơi, hệ số nhân 1.5, điểm lần lượt là 100, 200, 150 và điểm kiểm tra là 80:
Player 0: 100
Player 1: 200
Player 2: 150
Bonus applied to 80: 120Dùng std::stoi() và std::stod() để chuyển đổi đầu vào. Đừng quên các header guard trong tệp header.
Tự làm thử
#include <iostream>
#include <string>
#include "ScoreTracker.h"
using namespace std;
// TODO: Triển khai hàm khởi tạo ScoreTracker
ScoreTracker::ScoreTracker(size_t size, double multiplier) {
// TODO: Khởi tạo các thành viên và cấp phát mảng động
// Khởi tạo tất cả điểm số bằng 0
}
// TODO: Triển khai hàm hủy ScoreTracker
ScoreTracker::~ScoreTracker() {
// TODO: Giải phóng bộ nhớ động
}
// TODO: Triển khai toán tử truy cập bằng chỉ số không const
// TODO: Triển khai toán tử truy cập bằng chỉ số const
// TODO: Triển khai toán tử gọi hàm
// TODO: Triển khai phương thức getSize
size_t ScoreTracker::getSize() const {
// TODO: Trả về số lượng điểm số
}
int main() {
string line;
// Đọc số lượng người chơi
getline(cin, line);
size_t numPlayers = stoi(line);
// Đọc hệ số nhân điểm thưởng
getline(cin, line);
double multiplier = stod(line);
// TODO: Tạo ScoreTracker với numPlayers và multiplier
// TODO: Đọc điểm của từng người chơi và lưu bằng toán tử chỉ số
// TODO: Đọc điểm kiểm tra
// TODO: Hiển thị điểm của tất cả người chơi theo định dạng: "Player X: <score>"
// TODO: Hiển thị kết quả sau khi áp dụng hệ số thưởng theo định dạng: "Bonus applied to <test_score>: <result>"
return 0;
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng về OOP
Tệp bên ngoàiBiên dịch và tạo bản dựng C++Tệp header và tệp nguồnNamespace và phạm viGiới thiệu về OOP trong C++Lớp và đối tượngCon trỏ thisPhương thức (hàm thành viên)Thuộc tính (dữ liệu thành viên)Cơ bản về hàm khởi tạo và hàm hủyÔn tập: máy tính đơn giản4Thuộc tính của lớp
Thành viên đối tượng và thành viên tĩnhHàm truy xuất và hàm thiết lậpHàm thành viên hằngTừ khóa mutablePhương thức và biến tĩnhHàm và lớp bạnÔn tập: Trình quản lý tài khoản ngân hàng7Kế thừa
Kế thừa cơ bảnMức truy cập trong kế thừaThứ tự gọi hàm khởi tạo và hàm hủyGhi đè phương thứcHàm ảo và VTableĐa kế thừaKế thừa ảoÔn tập: hệ phân cấp nhân viên2Quản lý bộ nhớ
Bộ nhớ ngăn xếp và heapCon trỏ và tham chiếuBộ nhớ động (new/delete)Con trỏ thông minh trong C++RAII trong C++Ôn tập: Trình quản lý mảng động5Tính đóng gói
Phạm vi truy cập trong C++Tìm hiểu sâu về phạm vi truy cậpẨn thông tinStruct và lớpLớp lồng nhau và lớp bên trongÔn tập: hệ thống hồ sơ sinh viên8Đa hình
Đa hình lúc biên dịch và khi chạyNạp chồng hàmÔn lại hàm ảoHàm ảo thuần túyLớp trừu tượngThiết kế interface trong C++Ép kiểu động và RTTIÔn tập: Máy tính hình học3Hàm khởi tạo và hàm hủy
Hàm khởi tạo mặc địnhHàm khởi tạo có tham sốHàm khởi tạo sao chépHàm khởi tạo di chuyểnDanh sách khởi tạoHàm khởi tạo ủy quyềnTìm hiểu sâu về hàm hủyQuy tắc 3 / 5 / 0Ôn tập: lớp chuỗi6Nạp chồng toán tử
Giới thiệu về nạp chồng toán tửNạp chồng toán tử số họcNạp chồng toán tử so sánhToán tử luồngNạp chồng toán tử gánNạp chồng toán tử [] và ()Toán tử chuyển đổi kiểuÔn tập: lớp ma trận9Mẫu
Mẫu hàmMẫu lớpChuyên biệt hóa mẫuMẫu biến tham sốCơ bản về SFINAE và đặc điểm kiểuÔn tập: vùng chứa tổng quátTự luyện tập: Trình biên dịch C++ online