C++:算术运算符重载

c++: arithmetic operator overload

我有一个名为 HealthPoints 的 class,它有 hpmax_hp 成员。我想重载 + 运算符,所以它会像这样工作:

HealthPoints healthPoints1;
healthPoints1 -= 150; /* healthPoints1 now has 0 points out of 100 */
HealthPoints healthPoints2(150);
healthPoints2 -= 160; /* healthPoints2 now has 0 points out of 150 */
healthPoints2 = healthPoints1 + 160; /* healthPoints2 now has 100 points out of 100 */

我成功地让它工作了,但只是按照特定的顺序。如果我把数字放在对象之前,有没有办法让它识别出两者之间的数字并据此采取行动?目前它的工作方式,我得到 healthPoints2 现在有 160 分(满分 160)。

HealthPoints class:

class HealthPoints {
    public:
        static const int DEFAULT_MAXHP=100;
        static const int DEFAULT_HP=100;
        static const int MINIMUM_MAXHP=1;
        static const int MINIMUM_HP=0;
        explicit operator int() const;
        HealthPoints(int maxHP=HealthPoints::DEFAULT_MAXHP);
        ~HealthPoints() = default; // Destructor set to default
        HealthPoints(const HealthPoints&) = default; // Copy Constructor set to default
        HealthPoints& operator=(const HealthPoints&) = default; // Assignment operator set to default
        HealthPoints& operator+=(const HealthPoints& HP);
        HealthPoints& operator-=(const HealthPoints& HP);
        class InvalidArgument {};
    private:
        int m_maxHP;
        int m_HP;
        friend bool operator==(const HealthPoints& HP1, const HealthPoints& HP2);
        friend bool operator<(const HealthPoints& HP1, const HealthPoints& HP2);
        friend std::ostream& operator<<(std::ostream& os, const HealthPoints& HP);
};

HealthPoints::HealthPoints(int maxHP) {
    if(maxHP < HealthPoints::MINIMUM_MAXHP) {
        throw HealthPoints::InvalidArgument();
    }
    this->m_maxHP=maxHP;
    this->m_HP=m_maxHP;
}

HealthPoints operator+(const HealthPoints& HP1, const HealthPoints& HP2) {
    return HealthPoints(HP2)+=HP1;
}

HealthPoints operator-(const HealthPoints& HP1, const HealthPoints& HP2) {
    return HealthPoints(HP1)-=HP2;
}

HealthPoints& HealthPoints::operator+=(const HealthPoints& HP) {
    if(this->m_HP+HP.m_HP>this->m_maxHP) {
        this->m_HP=this->m_maxHP;
    } else {
        this->m_HP+=HP.m_HP;
    }
    return *this;
}

HealthPoints& HealthPoints::operator-=(const HealthPoints& HP) {
    if(this->m_HP-HP.m_HP>HealthPoints::MINIMUM_HP) {
        this->m_HP-=HP.m_HP;
    } else {
        this->m_HP=HealthPoints::MINIMUM_HP;
    }
    return *this;
}

我不完全确定您 HealthPoints class 的逻辑,因此请仔细检查下面的代码。不过,我的观点是实施:

    friend HealthPoints operator+(const HealthPoints& other, int value);
    friend HealthPoints operator+(int value, const HealthPoints& other);

实际上你只需要实现第一个,然后让第二个使用它:

HealthPoints operator+(const HealthPoints& hp, int value) {
    HealthPoints ret{hp};
    ret.m_HP = std::min(ret.m_maxHP, ret.m_HP + value);
    return ret;
}
HealthPoints operator+(int value, const HealthPoints& hp) {
    return hp + value;
}

您可以在此处查看实际效果:

[Demo]

int main() {
    HealthPoints hp1{100};
    hp1 -= 50;
    std::cout << "hp1: " << hp1 << "\n";
    auto hp2{hp1 + 10};
    std::cout << "hp2: " << hp2 << "\n";
    auto hp3{10 + hp2};
    std::cout << "hp3: " << hp3 << "\n";
}

// Outputs:
//   hp1: (max_HP = 100, HP = 50)
//   hp2: (max_HP = 100, HP = 60)
//   hp3: (max_HP = 100, HP = 70)

在此声明中:

healthPoints2 = healthPoints1 + 160;

您的 + 运算符正在创建一个新的 HealthPoints 对象,该对象是 healthPoints1 的副本,因此对象的 m_maxHP 设置为 100。然后将 160 添加到该对象,增加其 m_HP 但保留其 m_maxHP。然后将该对象分配给 healthPoints2,同时复制 m_HPm_maxHP 值。这就是 healthPoints2m_maxHP150 变为 100 的原因。

在此声明中:

healthPoints2 = 160 + healthPoints1;

您的 + 运算符正在创建一个新的 HealthPoints 对象,其 m_maxHP 设置为 160。然后将 healthPoints1 添加到该对象,增加其 m_HP 但保留其 m_maxHP。然后将该对象分配给 healthPoints2,同时复制 m_HPm_maxHP 值。这就是 healthPoints2m_maxHP150 变为 160 的原因。

如果您希望 operator 仅更新 m_HP 而不是更改 m_maxHP,您需要添加接受 int 值而不是 HealthPoints 个对象,例如:

HealthPoints& HealthPoints::operator+=(int value) {
    m_HP = std::min(m_HP + value, m_maxHP);
    return *this;
}

HealthPoints& HealthPoints::operator-=(int value) {
    m_HP = std::max(m_HP - value, HealthPoints::MINIMUM_HP);
    return *this;
}

HealthPoints operator+(const HealthPoints& HP, int value) {
    return HealthPoints(HP) += value;
}

HealthPoints operator+(int value, const HealthPoints& HP) {
    return HealthPoints(HP) += value;
}

HealthPoints operator-(const HealthPoints& HP, int value) {
    return HealthPoints(HP) -= value;
}

HealthPoints operator-(int value, const HealthPoints& HP) {
    return HealthPoints(HP) -= value;
}

然后,将 HealthPoints(int) 构造函数标记为 explicit 以避免在将 int 值传递给需要 HealthPoints 对象的参数时发生不需要的隐式转换。