文章目錄
- **Day6-2 成員訪問運算符重載(2025.03.25)**
- **1. 復習**
- **2. 成員訪問運算符重載**
- **2.1 箭頭運算符 (`->`) 重載**
- **(1) 語法**
- **2.2 解引用運算符 (`*`) 重載**
- **(1) 語法**
- **3. 代碼分析**
- **3.1 代碼結構**
- **3.2 代碼解析**
- **(1) `Data` 類**
- **(2) `SecondLayer` 類**
- **(3) `ThirdLayer` 類**
- **3.3 運行 `test()` 方法**
- **4. 總結**
Day6-2 成員訪問運算符重載(2025.03.25)
1. 復習
在上一節中,我們學習了 C++ 中的 輸入輸出流運算符重載(<<
和 >>
) 以及 下標運算符 []
和函數調用運算符 ()
的重載。本節我們將重點學習 成員訪問運算符(->
和 *
)的重載。
2. 成員訪問運算符重載
C++ 允許用戶自定義類的成員訪問方式,其中 ->
(箭頭運算符)和 *
(解引用運算符)是最常見的運算符之一。它們通常用于模擬智能指針或多層指針訪問。
2.1 箭頭運算符 (->
) 重載
(1) 語法
class A {
public:B* operator->();
};
作用:
- 允許
A
類的對象 像指針一樣訪問B
類的成員。 - 典型用途是在 封裝指針 的類(如智能指針)中重載
operator->
,使得用戶無需手動解引用即可訪問目標對象的成員。
注意事項:
- 返回值必須是一個指針或者引用,否則無法繼續訪問成員變量或函數。
- 如果返回的是對象的引用,則可以實現多層
->
重載。 operator->
不能改變調用對象自身,因此通常 不應該聲明為const
成員函數。
2.2 解引用運算符 (*
) 重載
(1) 語法
class A {
public:B& operator*();
};
作用:
- 允許
A
類的對象 像指針一樣進行解引用。 - 常見于智能指針的實現,使
*ptr
直接返回對象的引用,方便訪問其成員。
注意事項:
- 返回值一般是引用(如
B&
),這樣不會產生額外的拷貝。 - 適用于 封裝指針 的類,如智能指針或代理類。
3. 代碼分析
#include <iostream>
using namespace std;class Data
{
public:Data(int data = 0):_data(data){cout << "Data(int data = 0)" << endl;}~Data(){cout << "~Data()" << endl; }int getData() const{return _data;}
private:int _data;
};class SecondLayer
{
public:SecondLayer(Data* pData):_pData(pData){cout << "SecondLayer(Data* pData)" << endl;}//重載 -> 運算符Data* operator->(){return _pData;}//解引用重載運算符Data& operator*(){return *_pData;}~SecondLayer(){cout << "~SecondLayer()" << endl;if (_pData){delete _pData;_pData = nullptr;}}private:Data* _pData;
};class ThirdLayer
{
public:ThirdLayer(SecondLayer* pSecond):_pSecond(pSecond){cout << "ThirdLayer(SecondLayer* pSecond)" << endl;}//重載 -> 運算符SecondLayer& operator->() {return *_pSecond;}~ThirdLayer(){cout << "~ThirdLayer()" << endl;if (_pSecond){delete _pSecond;_pSecond = nullptr;}}private:SecondLayer* _pSecond;
};void test()
{/*Data* data = new Data(1);SecondLayer* second = new SecondLayer(data);ThirdLayer* third = new ThirdLayer(second);*/SecondLayer second(new Data(10));//棧對象//A類的對象調用B類的成員函數/*cout << "&second : " << &second << endl;cout << "second.operator->() :" << second.operator->() << endl;*/// 重載operator-> cout << "second.operator->()->getData() :" << second.operator->()->getData() << endl;cout << "second->getData() :" << second->getData() << endl;// 重載operator* cout << "(*second).getData()" << (*second).getData() << endl;ThirdLayer third(new SecondLayer(new Data(30)));//棧對象cout << "third->getData() : " << third->getData() << endl;//還原cout << "third.operator->().operator->()->getData()" << third.operator->().operator->()->getData();
}int main(int argc, char** argv)
{test();test();return 0;
}
3.1 代碼結構
上面的代碼實現了一個 三層封裝 的指針代理類,分別是:
Data
:數據類,包含一個_data
成員變量。SecondLayer
:封裝Data*
指針,并重載operator->
和operator*
。ThirdLayer
:封裝SecondLayer*
指針,并重載operator->
。
3.2 代碼解析
(1) Data
類
class Data
{
public:Data(int data = 0) : _data(data){cout << "Data(int data = 0)" << endl;}~Data(){cout << "~Data()" << endl;}int getData() const{return _data;}
private:int _data;
};
Data
類封裝了一個int
類型的數據_data
,提供了getData()
方法用于獲取數據值。- 構造函數、析構函數用于跟蹤對象的創建和銷毀。
(2) SecondLayer
類
class SecondLayer
{
public:SecondLayer(Data* pData) : _pData(pData){cout << "SecondLayer(Data* pData)" << endl;}// 重載 -> 運算符Data* operator->(){return _pData;}// 解引用運算符 *Data& operator*(){return *_pData;}~SecondLayer(){cout << "~SecondLayer()" << endl;if (_pData){delete _pData;_pData = nullptr;}}private:Data* _pData;
};
- 封裝
Data*
指針,并提供訪問Data
成員的方式。 operator->()
返回_pData
指針,使得SecondLayer
對象 可以像指針一樣使用->
訪問Data
的方法。operator*()
返回_pData
所指向的Data
對象的引用,使*second
直接返回Data
對象。
示例:
SecondLayer second(new Data(10));
cout << second->getData() << endl; // 等價于 second.operator->()->getData()
cout << (*second).getData() << endl; // 等價于 second.operator*().getData()
(3) ThirdLayer
類
class ThirdLayer
{
public:ThirdLayer(SecondLayer* pSecond) : _pSecond(pSecond){cout << "ThirdLayer(SecondLayer* pSecond)" << endl;}// 重載 -> 運算符SecondLayer& operator->(){return *_pSecond;}~ThirdLayer(){cout << "~ThirdLayer()" << endl;if (_pSecond){delete _pSecond;_pSecond = nullptr;}}private:SecondLayer* _pSecond;
};
ThirdLayer
封裝了SecondLayer*
指針,并提供operator->()
使其 可以像SecondLayer
一樣使用->
訪問Data
的方法。- 實現兩層
->
重載,使得ThirdLayer
可以連續訪問Data
成員。
示例:
ThirdLayer third(new SecondLayer(new Data(30)));
cout << third->getData() << endl; // 等價于 third.operator->().operator->()->getData()
3.3 運行 test()
方法
void test()
{SecondLayer second(new Data(10));cout << "second->getData() :" << second->getData() << endl;cout << "(*second).getData()" << (*second).getData() << endl;ThirdLayer third(new SecondLayer(new Data(30)));cout << "third->getData() : " << third->getData() << endl;cout << "third.operator->().operator->()->getData() : " << third.operator->().operator->()->getData();
}
輸出:
Data(int data = 0)
SecondLayer(Data* pData)
second->getData() : 10
(*second).getData() : 10
Data(int data = 0)
SecondLayer(Data* pData)
ThirdLayer(SecondLayer* pSecond)
third->getData() : 30
third.operator->().operator->()->getData() : 30
~ThirdLayer()
~SecondLayer()
~Data()
~SecondLayer()
~Data()
SecondLayer
允許訪問Data
對象。ThirdLayer
允許訪問SecondLayer
,最終可訪問Data
。- 多層指針訪問的代理模式生效,并且析構時正確釋放了內存。
4. 總結
運算符 | 作用 | 適用場景 | 返回值類型 |
---|---|---|---|
operator->() | 允許對象像指針一樣訪問成員 | 智能指針、代理類 | 指針或引用 |
operator*() | 允許對象像指針一樣解引用 | 智能指針、代理類 | 引用 |
關鍵點:
operator->()
需要返回指針或引用,可以連續調用->
。operator*()
需要返回對象的引用,避免拷貝,提高性能。- 適用于封裝指針的類,如智能指針和代理類。
本節學習了 成員訪問運算符 ->
和 *
的重載,掌握它們的用法可以更好地理解 智能指針 和 代理模式。