文章目录
-
- [**Day6-2 成员访问运算符重载(2025.03.25)**](#Day6-2 成员访问运算符重载(2025.03.25))
- [**1. 复习**](#1. 复习)
- [**2. 成员访问运算符重载**](#2. 成员访问运算符重载)
-
- [**2.1 箭头运算符 (`->`) 重载**](#2.1 箭头运算符 (
->) 重载) -
- [**(1) 语法**](#(1) 语法)
- [**2.2 解引用运算符 (`*`) 重载**](#2.2 解引用运算符 (
*) 重载) -
- [**(1) 语法**](#(1) 语法)
- [**2.1 箭头运算符 (`->`) 重载**](#2.1 箭头运算符 (
- [**3. 代码分析**](#3. 代码分析)
-
- [**3.1 代码结构**](#3.1 代码结构)
- [**3.2 代码解析**](#3.2 代码解析)
-
- [**(1) `Data` 类**](#(1)
Data类) - [**(2) `SecondLayer` 类**](#(2)
SecondLayer类) - [**(3) `ThirdLayer` 类**](#(3)
ThirdLayer类)
- [**(1) `Data` 类**](#(1)
- [**3.3 运行 `test()` 方法**](#3.3 运行
test()方法)
- [**4. 总结**](#4. 总结)
Day6-2 成员访问运算符重载(2025.03.25)
1. 复习
在上一节中,我们学习了 C++ 中的 输入输出流运算符重载(<< 和 >>) 以及 下标运算符 [] 和函数调用运算符 () 的重载。本节我们将重点学习 成员访问运算符(-> 和 *)的重载。
2. 成员访问运算符重载
C++ 允许用户自定义类的成员访问方式,其中 ->(箭头运算符)和 *(解引用运算符)是最常见的运算符之一。它们通常用于模拟智能指针或多层指针访问。
2.1 箭头运算符 (->) 重载
(1) 语法
cpp
class A {
public:
B* operator->();
};
作用:
- 允许
A类的对象 像指针一样访问B类的成员。 - 典型用途是在 封装指针 的类(如智能指针)中重载
operator->,使得用户无需手动解引用即可访问目标对象的成员。
注意事项:
- 返回值必须是一个指针或者引用,否则无法继续访问成员变量或函数。
- 如果返回的是对象的引用 ,则可以实现多层
->重载。 operator->不能改变调用对象自身 ,因此通常 不应该声明为const成员函数。
2.2 解引用运算符 (*) 重载
(1) 语法
cpp
class A {
public:
B& operator*();
};
作用:
- 允许
A类的对象 像指针一样进行解引用。 - 常见于智能指针的实现,使
*ptr直接返回对象的引用,方便访问其成员。
注意事项:
- 返回值一般是引用 (如
B&),这样不会产生额外的拷贝。 - 适用于 封装指针 的类,如智能指针或代理类。
3. 代码分析
cpp
#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 类
cpp
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 类
cpp
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对象。
示例:
cpp
SecondLayer second(new Data(10));
cout << second->getData() << endl; // 等价于 second.operator->()->getData()
cout << (*second).getData() << endl; // 等价于 second.operator*().getData()
(3) ThirdLayer 类
cpp
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成员。
示例:
cpp
ThirdLayer third(new SecondLayer(new Data(30)));
cout << third->getData() << endl; // 等价于 third.operator->().operator->()->getData()
3.3 运行 test() 方法
cpp
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*()需要返回对象的引用,避免拷贝,提高性能。- 适用于封装指针的类,如智能指针和代理类。
本节学习了 成员访问运算符 -> 和 * 的重载 ,掌握它们的用法可以更好地理解 智能指针 和 代理模式。