C++中左移運(yùn)算符重載的實(shí)現(xiàn)
在 C++ 中,左移運(yùn)算符(<<) 最常用的場景是配合 cout 輸出數(shù)據(jù)(如 cout << “hello”)。對于自定義類型(如類、結(jié)構(gòu)體),默認(rèn)無法直接用 cout << 對象 輸出,需通過重載 << 運(yùn)算符實(shí)現(xiàn),這也是 << 運(yùn)算符重載最核心的應(yīng)用場景。
一、左移運(yùn)算符重載的核心特點(diǎn)
1、<< 是雙目運(yùn)算符:左操作數(shù)是 ostream 對象(如 cout),右操作數(shù)是自定義類型對象;
2、必須重載為全局函數(shù) / 友元:若重載為成員函數(shù),左操作數(shù)會被綁定為當(dāng)前類對象(如 obj << cout),違反 cout << obj 的使用直覺,因此只能用全局函數(shù),且需聲明為類的友元(以訪問私有成員);
3、返回值為 ostream&:支持鏈?zhǔn)捷敵觯ㄈ?cout << obj1 << obj2 << endl);
4、不修改操作數(shù):通常用 const 修飾自定義類型參數(shù),保證不修改對象。
二、重載語法與步驟
- 核心語法
// 類內(nèi)聲明友元(需訪問私有成員時)
friend ostream& operator<<(ostream& os, const 類名& obj);
// 全局定義重載函數(shù)
ostream& operator<<(ostream& os, const 類名& obj) {
// 自定義輸出邏輯(如輸出對象的成員)
os << 成員1 << " " << 成員2;
return os; // 返回ostream對象,支持鏈?zhǔn)捷敵?
}
- 關(guān)鍵說明
ostream& 返回值:返回傳入的 os 引用(而非臨時對象),確保鏈?zhǔn)秸{(diào)用時 cout 是同一個對象;
const 類名& obj:用引用避免拷貝,const 保證不修改對象(即使輸出常量對象也能生效);
友元聲明:僅當(dāng)需要訪問類的私有 / 保護(hù)成員時才需要,若成員是 public,可省略友元,直接通過公共接口訪問。
三、基礎(chǔ)示例:自定義類輸出
以復(fù)數(shù)類為例,實(shí)現(xiàn) cout << 復(fù)數(shù)對象 輸出實(shí)部和虛部:
#include <iostream>
using namespace std;
class Complex {
private:
double real; // 實(shí)部(私有)
double imag; // 虛部(私有)
public:
// 構(gòu)造函數(shù)
Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}
// 聲明 << 運(yùn)算符為友元(訪問私有成員)
friend ostream& operator<<(ostream& os, const Complex& c);
};
// 全局定義左移運(yùn)算符重載
ostream& operator<<(ostream& os, const Complex& c) {
// 自定義輸出格式
os << c.real << " + " << c.imag << "i";
return os; // 返回ostream引用,支持鏈?zhǔn)捷敵?
}
int main() {
Complex c1(1.5, 2.5), c2(3.5, 4.5);
// 基礎(chǔ)輸出
cout << "c1: " << c1 << endl; // 輸出:c1: 1.5 + 2.5i
// 鏈?zhǔn)捷敵?
cout << "c1 = " << c1 << ", c2 = " << c2 << endl; // 輸出:c1 = 1.5 + 2.5i, c2 = 3.5 + 4.5i
return 0;
}
四、進(jìn)階示例:支持多格式輸出 + 非友元重載
若不想用友元(避免破壞封裝),可通過公共接口(getter 函數(shù))訪問成員,實(shí)現(xiàn)非友元重載:
#include <iostream>
using namespace std;
class Student {
private:
string name;
int age;
double score;
public:
Student(string n, int a, double s) : name(n), age(a), score(s) {}
// 公共getter接口
string getName() const { return name; }
int getAge() const { return age; }
double getScore() const { return score; }
};
// 非友元重載 <<:通過getter訪問成員
ostream& operator<<(ostream& os, const Student& stu) {
os << "姓名:" << stu.getName()
<< ",年齡:" << stu.getAge()
<< ",成績:" << stu.getScore();
return os;
}
int main() {
Student stu("張三", 18, 95.5);
cout << stu << endl; // 輸出:姓名:張三,年齡:18,成績:95.5
return 0;
}
五、支持自定義輸出流(如文件流)
<< 重載不僅支持 cout(控制臺輸出),還支持所有 ostream 派生類(如 ofstream 文件輸出),因?yàn)橹剌d函數(shù)的參數(shù)是基類 ostream&:
#include <iostream>
#include <fstream>
using namespace std;
class Complex {
private:
double real, imag;
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
friend ostream& operator<<(ostream& os, const Complex& c);
};
ostream& operator<<(ostream& os, const Complex& c) {
os << c.real << " + " << c.imag << "i";
return os;
}
int main() {
Complex c(2.5, 3.5);
// 輸出到控制臺
cout << "控制臺輸出:" << c << endl;
// 輸出到文件
ofstream fout("complex.txt");
if (fout.is_open()) {
fout << "文件輸出:" << c << endl;
fout.close();
}
return 0;
}
運(yùn)行后,complex.txt 文件中會寫入:文件輸出:2.5 + 3.5i。
六、常見誤區(qū)與注意事項(xiàng)
1、錯誤地重載為成員函數(shù):
// 錯誤示例:成員函數(shù)重載 <<,左操作數(shù)是Complex對象,使用時需寫 c << cout,違反直覺
class Complex {
public:
ostream& operator<<(ostream& os) {
os << real << " + " << imag << "i";
return os;
}
};
// 調(diào)用:c1 << cout; // 極其反人類,絕對避免!
2、返回值錯誤:
若返回 void,無法支持鏈?zhǔn)捷敵觯ㄈ?cout << c1 << c2 會報(bào)錯);
若返回 ostream(值返回),會拷貝 cout(ostream 不支持拷貝),導(dǎo)致編譯錯誤,必須返回 ostream&(引用)。
3、未用 const 修飾對象參數(shù):
若參數(shù)是 Complex& c(無 const),則無法輸出常量對象(如 const Complex c(1,2); cout << c; 報(bào)錯),必須加 const。
4、友元的濫用:
僅當(dāng)需要訪問私有成員時才聲明友元,優(yōu)先通過 getter 接口實(shí)現(xiàn)非友元重載,減少封裝破壞。
七、與右移運(yùn)算符(>>)重載的配合
左移(<<)用于輸出,右移(>>)用于輸入,通常成對重載,示例如下:
#include <iostream>
using namespace std;
class Complex {
private:
double real, imag;
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// 重載 <<(輸出)
friend ostream& operator<<(ostream& os, const Complex& c);
// 重載 >>(輸入)
friend istream& operator>>(istream& is, Complex& c);
};
ostream& operator<<(ostream& os, const Complex& c) {
os << c.real << " + " << c.imag << "i";
return os;
}
istream& operator>>(istream& is, Complex& c) {
// 自定義輸入格式:輸入兩個數(shù),分別賦值給實(shí)部和虛部
cout << "請輸入實(shí)部和虛部(空格分隔):";
is >> c.real >> c.imag;
return is;
}
int main() {
Complex c;
cin >> c; // 輸入:3 4
cout << "你輸入的復(fù)數(shù)是:" << c << endl; // 輸出:3 + 4i
return 0;
}
總結(jié)
左移運(yùn)算符(<<)重載的核心目的是讓自定義類型支持 cout(或其他 ostream)輸出;
必須重載為全局函數(shù)(友元按需聲明),返回 ostream& 以支持鏈?zhǔn)捷敵觯?br />參數(shù)需用 const 類名& 修飾,保證不修改對象且避免拷貝;
可兼容所有 ostream 派生類(控制臺、文件等),通用性強(qiáng);
通常與 >> 運(yùn)算符重載配合,實(shí)現(xiàn)自定義類型的輸入輸出。
到此這篇關(guān)于C++中左移運(yùn)算符重載的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C++ 左移運(yùn)算符重載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言用指針函數(shù)尋找數(shù)組中的最大值與次大值
這篇文章主要給大家介紹了關(guān)于C語言用指針函數(shù)尋找數(shù)組中的最大值與次大值的相關(guān)資料,該代碼通過定義一個名為LargestTow的函數(shù)來找出數(shù)組中的最大值和次大值,并將結(jié)果分別存入指針?biāo)赶虻膬?nèi)存單元中,需要的朋友可以參考下2024-11-11
一文搞懂C++中的四種強(qiáng)制類型轉(zhuǎn)換
很多朋友向小編了解C語言中怎么進(jìn)行強(qiáng)制類型轉(zhuǎn)換呢?在這小編告訴大家強(qiáng)制類型轉(zhuǎn)換可以分為兩種,一種是隱式類型轉(zhuǎn)換一種是顯示類型轉(zhuǎn)換,下面通過示例代碼給大家介紹下,需要的朋友參考下吧2021-07-07
深入const int *p與int * const p的區(qū)別詳解(常量指針與指向常量的指針)
本篇文章是對const int *p與int * const p的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06

