Menu
CoddyTech

Nạp chồng toán tử so sánh

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 42 trên 104.

Các toán tử so sánh như ==, !=, <, >, <= và >= cho phép bạn so sánh các đối tượng thuộc lớp tùy chỉnh. Các toán tử này trả về giá trị bool và nên được đánh dấu là const vì chúng không thay đổi toán hạng nào.

class Date {
    int year, month, day;
    
public:
    Date(int y, int m, int d) : year(y), month(m), day(d) {}
    
    bool operator==(const Date& other) const {
        return year == other.year && 
               month == other.month && 
               day == other.day;
    }
    
    bool operator<(const Date& other) const {
        if (year != other.year) return year < other.year;
        if (month != other.month) return month < other.month;
        return day < other.day;
    }
};

Một kỹ thuật hữu ích là triển khai các toán tử so sánh khác dựa trên những toán tử bạn đã định nghĩa. Khi đã có == và <, bạn có thể dễ dàng tạo ra các toán tử còn lại:

bool operator!=(const Date& other) const {
    return !(*this == other);
}

bool operator>(const Date& other) const {
    return other < *this;
}

bool operator<=(const Date& other) const {
    return !(other < *this);
}

bool operator>=(const Date& other) const {
    return !(*this < other);
}

Cách làm này giúp giảm trùng lặp code và đảm bảo tất cả toán tử so sánh hoạt động nhất quán. Nếu sau này bạn thay đổi cách hoạt động của phép bằng hoặc phép nhỏ hơn, các toán tử khác sẽ tự động đồng bộ.

challenge icon

Thử thách

Dễ

Hãy xây dựng một lớp Version đại diện cho số phiên bản phần mềm (chẳng hạn như 2.1.0 hoặc 3.0.5) và hỗ trợ cả sáu toán tử so sánh. Đây là một trường hợp sử dụng thực tế, trong đó việc so sánh phiên bản giúp xác định phần mềm nào mới hơn, rất phù hợp để luyện tập nạp chồng toán tử so sánh.

Bạn sẽ tạo hai tệp để sắp xếp code:

  • Version.h: Định nghĩa lớp Version lưu ba số nguyên đại diện cho các thành phần phiên bản major, minor và patch. Lớp của bạn cần hỗ trợ:
    • Một hàm khởi tạo nhận các giá trị major, minor và patch
    • Các hàm lấy giá trị cho từng thành phần: getMajor(), getMinor(), getPatch() (đều là const)
    • Cả sáu toán tử so sánh: ==, !=, <, >, <=, >=
    • Một phương thức toString() trả về phiên bản dưới dạng chuỗi theo định dạng "major.minor.patch"

    Triển khai trực tiếp == và <, sau đó định nghĩa bốn toán tử còn lại dựa trên hai toán tử này. Với phép so sánh nhỏ hơn, hãy so sánh major trước, sau đó so sánh minor nếu major bằng nhau, rồi so sánh patch nếu cả major lẫn minor đều bằng nhau. Tất cả toán tử so sánh phải là hàm thành viên const.

  • main.cpp: Đọc sáu số nguyên từ đầu vào, đại diện cho hai phiên bản (major1, minor1, patch1, major2, minor2, patch2 trên các dòng riêng biệt). Tạo hai đối tượng Version và so sánh chúng bằng tất cả các toán tử của bạn.

    Định dạng đầu ra:

    Version 1: <v1>
    Version 2: <v2>
    v1 == v2: <true/false>
    v1 != v2: <true/false>
    v1 < v2: <true/false>
    v1 > v2: <true/false>
    v1 <= v2: <true/false>
    v1 >= v2: <true/false>

    In true hoặc false (chữ thường) cho kết quả của mỗi phép so sánh.

Kỹ thuật quan trọng ở đây là triển khai bốn toán tử suy ra (!=, >, <=, >=) chỉ bằng == và <. Cách này giảm việc lặp lại code và đảm bảo tất cả toán tử luôn nhất quán nếu sau này bạn thay đổi logic so sánh.

Chuyển các chuỗi đầu vào thành số nguyên bằng std::stoi(). Dùng std::to_string() để tạo chuỗi phiên bản. Đừng quên các header guard trong tệp header.

Tự làm thử

#include <iostream>
#include <string>
#include "Version.h"

using namespace std;

int main() {
    // Đọc sáu số nguyên cho hai phiên bản
    string line;
    
    getline(cin, line);
    int major1 = stoi(line);
    
    getline(cin, line);
    int minor1 = stoi(line);
    
    getline(cin, line);
    int patch1 = stoi(line);
    
    getline(cin, line);
    int major2 = stoi(line);
    
    getline(cin, line);
    int minor2 = stoi(line);
    
    getline(cin, line);
    int patch2 = stoi(line);

    // TODO: Tạo hai đối tượng Version
    
    // TODO: In ra Version 1 và Version 2 bằng toString()
    
    // TODO: So sánh bằng cả sáu toán tử và in ra kết quả
    // Dùng "true" hoặc "false" (chữ thường) cho mỗi phép so sánh
    // Định dạng: "v1 == v2: true" hoặc "v1 == v2: false"
    
    return 0;
}
quiz iconTự kiểm tra

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

Tự luyện tập: Trình biên dịch C++ online