首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++ 運算符重載陷阱:加法正確減法異常的副作用分析

     編輯:程式設計疑難解答

問題代碼核心

RMB RMB::operator +(RMB b) {
    yuan = yuan + b.yuan;   // 修改了左操作數 this 的成員!
    jiao = jiao + b.jiao;
    fen = fen + b.fen;
    // ... 進位邏輯
    return RMB(yuan, jiao, fen);
}

錯誤本質

運算符 + 應為純函數,不修改操作數。但代碼中直接修改了 this->yuan、jiao、fen,導致:

  1. e = c + d; 執行後,c 的值被永久修改(元、角、分均增加)。
  2. 隨後 f = d - c; 使用的是 已被修改的 c,結果當然錯誤。
  3. 註釋掉減法、改用 c1, d1 重新初始化,結果正確,印證了副作用。

正確實現模式

1. 加法:創建臨時對象,不修改 this

RMB RMB::operator +(const RMB& b) const { // const 保證不修改 this
    int ny = yuan + b.yuan;
    int nj = jiao + b.jiao;
    int nf = fen + b.fen;
    
    // 進位處理(使用局部變量)
    if (nf >= 10) { nf -= 10; nj++; }
    if (nj >= 10) { nj -= 10; ny++; }
    
    return RMB(ny, nj, nf); // 返回新對象
}

2. 減法:同理,不修改 this,處理借位

RMB RMB::operator -(const RMB& b) const {
    int ny = yuan, nj = jiao, nf = fen;
    
    // 借位邏輯
    if (nf < b.fen) {
        if (nj > 0) { nf += 10; nj--; }
        else if (ny > 0) { ny--; nj += 9; nf += 10; }
        else { /* 處理負數或拋出異常 */ }
    }
    nf -= b.fen;
    
    if (nj < b.jiao) {
        if (ny > 0) { ny--; nj += 10; }
        else { /* 處理負數 */ }
    }
    nj -= b.jiao;
    ny -= b.yuan;
    
    return RMB(ny, nj, nf);
}

最佳實踐總結

原則做法理由
參數傳 const 引用const RMB& b避免拷貝開銷,防止誤修改參數
成員函數加 constoperator+(...) const編譯器強制檢查不修改 this,語義明確
使用局部變量計算int ny=yuan+...不污染原對象,線程安全
返回值而非引用RMB 而非 RMB&返回臨時對象,生命週期由調用方管理

驗證測試

int main() {
    RMB c(1, 2, 1), d(3, 3, 3);
    RMB e = c + d; // c 不變
    RMB f = d - c; // 使用原始 c
    c.display(); // 仍為 1元2角1分
    d.display(); // 仍為 3元3角3分
    e.display(); // 4元5角4分
    f.display(); // 2元1角2分
}

總結

運算符重載的核心規範:「不修改操作數,返回新值」。原代碼在 operator+ 中修改 this 導致連續調用時狀態污染。加上 const 資格、使用局部變量計算、傳 const 引用,可從語法層面杜絕此類 Bug。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved