文章目录
- **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*()
需要返回对象的引用,避免拷贝,提高性能。- 适用于封装指针的类,如智能指针和代理类。
本节学习了 成员访问运算符 ->
和 *
的重载,掌握它们的用法可以更好地理解 智能指针 和 代理模式。