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

C++ 友元函數常見錯誤:參數傳值導致無法修改原對象

     編輯:程式設計綜合問答

問題現場

用戶提供兩張圖片(代碼截圖),提示「錯字哪裡啊」。根據最佳回答提示:

add 函數的參數復制方式,不會修改原對象,看看書上的交換值的例子就清楚了。

核心錯誤:值傳遞 vs 引用傳遞

友元函數雖能訪問私有成員,但參數傳遞機制遵循普通函數規則。典型錯誤代碼:

// 錯誤示範:參數按值傳遞
friend void add(MyClass obj);  // 或實現時 void add(MyClass obj)

void add(MyClass obj) {  // 這裡 obj 是副本
    obj.data += 10;      // 修改的是副本,原對象不變
}

修正方案:使用引用參數

// 正確聲明
friend void add(MyClass& obj);  // 注意 &

void add(MyClass& obj) {  // 引用綁定原對象
    obj.data += 10;       // 真正修改原對象
}

為什麼友元函數特別容易踩這個坑?

  1. 關注點偏移:初學者專注於「友元能訪問 private」,忽略了「參數怎麼傳」這一基礎語義。
  2. 交換函數對比:教材常用 swap(int &a, int &b) 強調引用修改實參,友元函數同理。
  3. const 正確性:若不需修改,應聲明 const MyClass&;需修改則用非 const 引用。

完整可編譯示例

#include <iostream>
using namespace std;

class Counter {
    int count;
public:
    Counter(int c = 0) : count(c) {}
    void print() const { cout << "count = " << count << endl; }

    // 友元函數聲明:使用引用參數
    friend void increment(Counter& c, int delta);
    friend void safeRead(const Counter& c);  // 僅讀取,用 const 引用
};

// 修改原對象
void increment(Counter& c, int delta) {
    c.count += delta;
}

// 僅讀取
void safeRead(const Counter& c) {
    cout << "safeRead: " << c.count << endl;
    // c.count = 100; // 編譯錯誤:const 引用不可修改
}

int main() {
    Counter obj(5);
    obj.print();           // count = 5
    increment(obj, 3);     // 通過友元修改
    obj.print();           // count = 8
    safeRead(obj);         // safeRead: 8
    return 0;
}

延伸:運算符重載中的同類問題

重載 operator+、operator<< 等時同樣適用:

  • operator+ 通常返回新對象,參數用 const T&。
  • operator<< 第二參數用 const T&。
  • operator>> 第二參數用 T&(需修改目標對象)。
  • operator=、operator+= 等修改左操作數,參數用 T& 返回 T&。

總結

友元函數不是魔法,參數傳遞遵循 C++ 基礎規則。需要修改原對象 → 非 const 引用;僅讀取 → const 引用;絕不按值傳遞大對象(除非刻意複製)。下次寫友元時,先問自己:「這裡要改原對象嗎?」再決定加不加 &。

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