C++11&QT复习 (五)

[复制链接]
发表于 2025-10-8 20:23:30 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
Day6-2 成员访问运算符重载(2025.03.25)

1. 复习

在上一节中,我们学习了 C++ 中的 输入输出流运算符重载(<< 和 >>) 以及 下标运算符 [] 和函数调用运算符 () 的重载。本节我们将重点学习 成员访问运算符(-> 和 *)的重载。

2. 成员访问运算符重载

C++ 答应用户自界说类的成员访问方式,此中 ->(箭头运算符)和 *(解引用运算符)是最常见的运算符之一。它们通常用于模仿智能指针或多层指针访问。
2.1 箭头运算符 (->) 重载

(1) 语法

  1. class A {
  2. public:
  3.     B* operator->();
  4. };
复制代码
作用:


  • 答应 A 类的对象 像指针一样访问 B 类的成员。
  • 范例用途是在 封装指针 的类(如智能指针)中重载 operator->,使得用户无需手动解引用即可访问目标对象的成员。
注意事项:

  • 返回值必须是一个指针大概引用,否则无法继续访问成员变量或函数。
  • 假如返回的是对象的引用,则可以实现多层 -> 重载。
  • operator-> 不能改变调用对象自身,因此通常 不应该声明为 const 成员函数。

2.2 解引用运算符 (*) 重载

(1) 语法

  1. class A {
  2. public:
  3.     B& operator*();
  4. };
复制代码
作用:


  • 答应 A 类的对象 像指针一样举行解引用。
  • 常见于智能指针的实现,使 *ptr 直接返回对象的引用,方便访问其成员。
注意事项:

  • 返回值一样寻常是引用(如 B&),如许不会产生额外的拷贝。
  • 实用于 封装指针 的类,如智能指针或署理类。

3. 代码分析

  1. #include <iostream>
  2. using namespace std;
  3. class Data
  4. {
  5. public:
  6.         Data(int data = 0)
  7.                 :_data(data)
  8.         {
  9.                 cout << "Data(int data = 0)" << endl;
  10.         }
  11.         ~Data()
  12.         {
  13.                 cout << "~Data()" << endl;
  14.         }
  15.         int getData() const
  16.         {
  17.                 return _data;
  18.         }
  19. private:
  20.         int _data;
  21. };
  22. class SecondLayer
  23. {
  24. public:
  25.         SecondLayer(Data* pData)
  26.         :_pData(pData)
  27.         {
  28.                 cout << "SecondLayer(Data* pData)" << endl;
  29.         }
  30.         //重载 -> 运算符
  31.         Data* operator->()
  32.         {
  33.                 return _pData;
  34.         }
  35.         //解引用重载运算符
  36.         Data& operator*()
  37.         {
  38.                 return *_pData;
  39.         }
  40.         ~SecondLayer()
  41.         {
  42.                 cout << "~SecondLayer()" << endl;
  43.                 if (_pData)
  44.                 {
  45.                         delete _pData;
  46.                         _pData = nullptr;
  47.                 }
  48.         }
  49. private:
  50.         Data* _pData;
  51. };
  52. class ThirdLayer
  53. {
  54. public:
  55.         ThirdLayer(SecondLayer* pSecond)
  56.                 :_pSecond(pSecond)
  57.         {
  58.                 cout << "ThirdLayer(SecondLayer* pSecond)" << endl;
  59.         }
  60.         //重载 -> 运算符
  61.         SecondLayer& operator->()
  62.         {
  63.                 return *_pSecond;
  64.         }
  65.         ~ThirdLayer()
  66.         {
  67.                 cout << "~ThirdLayer()" << endl;
  68.                 if (_pSecond)
  69.                 {
  70.                         delete _pSecond;
  71.                         _pSecond = nullptr;
  72.                 }
  73.         }
  74. private:
  75.         SecondLayer* _pSecond;
  76. };
  77. void test()
  78. {
  79.         /*Data* data = new Data(1);
  80.         SecondLayer* second = new SecondLayer(data);
  81.         ThirdLayer* third = new ThirdLayer(second);*/
  82.         SecondLayer second(new Data(10));//栈对象
  83.         //A类的对象调用B类的成员函数
  84.         /*cout << "&second : " << &second << endl;
  85.         cout << "second.operator->() :" << second.operator->() << endl;*/
  86.         //  重载operator->  
  87.         cout << "second.operator->()->getData() :" << second.operator->()->getData() << endl;
  88.         cout << "second->getData() :" << second->getData() << endl;
  89.         //  重载operator*
  90.         cout << "(*second).getData()" << (*second).getData() << endl;
  91.         ThirdLayer third(new SecondLayer(new Data(30)));//栈对象
  92.         cout << "third->getData() : " << third->getData() << endl;
  93.         //还原
  94.         cout << "third.operator->().operator->()->getData()" << third.operator->().operator->()->getData();
  95. }
  96. int main(int argc, char** argv)
  97. {
  98.         test();
  99.         test();
  100.         return 0;
  101. }
复制代码
3.1 代码布局

上面的代码实现了一个 三层封装 的指针署理类,分别是:


  • Data:数据类,包罗一个 _data 成员变量。
  • SecondLayer:封装 Data* 指针,并重载 operator-> 和 operator*。
  • ThirdLayer:封装 SecondLayer* 指针,并重载 operator->。

3.2 代码分析

(1) Data 类

  1. class Data
  2. {
  3. public:
  4.     Data(int data = 0) : _data(data)
  5.     {
  6.         cout << "Data(int data = 0)" << endl;
  7.     }
  8.     ~Data()
  9.     {
  10.         cout << "~Data()" << endl;
  11.     }
  12.     int getData() const
  13.     {
  14.         return _data;
  15.     }
  16. private:
  17.     int _data;
  18. };
复制代码


  • Data 类封装了一个 int 范例的数据 _data,提供了 getData() 方法用于获取数据值。
  • 构造函数、析构函数用于跟踪对象的创建和烧毁。

(2) SecondLayer 类

  1. class SecondLayer
  2. {
  3. public:
  4.     SecondLayer(Data* pData) : _pData(pData)
  5.     {
  6.         cout << "SecondLayer(Data* pData)" << endl;
  7.     }
  8.     // 重载 -> 运算符
  9.     Data* operator->()
  10.     {
  11.         return _pData;
  12.     }
  13.     // 解引用运算符 *
  14.     Data& operator*()
  15.     {
  16.         return *_pData;
  17.     }
  18.     ~SecondLayer()
  19.     {
  20.         cout << "~SecondLayer()" << endl;
  21.         if (_pData)
  22.         {
  23.             delete _pData;
  24.             _pData = nullptr;
  25.         }
  26.     }
  27. private:
  28.     Data* _pData;
  29. };
复制代码


  • 封装 Data* 指针,并提供访问 Data 成员的方式。
  • operator->() 返回 _pData 指针,使得 SecondLayer 对象 可以像指针一样使用 -> 访问 Data 的方法。
  • operator*() 返回 _pData 所指向的 Data 对象的引用,使 *second 直接返回 Data 对象。
示例:
  1. SecondLayer second(new Data(10));
  2. cout << second->getData() << endl;  // 等价于 second.operator->()->getData()
  3. cout << (*second).getData() << endl; // 等价于 second.operator*().getData()
复制代码

(3) ThirdLayer 类

  1. class ThirdLayer
  2. {
  3. public:
  4.     ThirdLayer(SecondLayer* pSecond) : _pSecond(pSecond)
  5.     {
  6.         cout << "ThirdLayer(SecondLayer* pSecond)" << endl;
  7.     }
  8.     // 重载 -> 运算符
  9.     SecondLayer& operator->()
  10.     {
  11.         return *_pSecond;
  12.     }
  13.     ~ThirdLayer()
  14.     {
  15.         cout << "~ThirdLayer()" << endl;
  16.         if (_pSecond)
  17.         {
  18.             delete _pSecond;
  19.             _pSecond = nullptr;
  20.         }
  21.     }
  22. private:
  23.     SecondLayer* _pSecond;
  24. };
复制代码


  • ThirdLayer 封装了 SecondLayer* 指针,并提供 operator->() 使其 可以像 SecondLayer 一样使用 -> 访问 Data 的方法。
  • 实现两层 -> 重载,使得 ThirdLayer 可以连续访问 Data 成员。
示例:
  1. ThirdLayer third(new SecondLayer(new Data(30)));
  2. cout << third->getData() << endl;  // 等价于 third.operator->().operator->()->getData()
复制代码

3.3 运行 test() 方法

  1. void test()
  2. {
  3.     SecondLayer second(new Data(10));
  4.     cout << "second->getData() :" << second->getData() << endl;
  5.     cout << "(*second).getData()" << (*second).getData() << endl;
  6.     ThirdLayer third(new SecondLayer(new Data(30)));
  7.     cout << "third->getData() : " << third->getData() << endl;
  8.     cout << "third.operator->().operator->()->getData() : " << third.operator->().operator->()->getData();
  9. }
复制代码
输出:
  1. Data(int data = 0)
  2. SecondLayer(Data* pData)
  3. second->getData() : 10
  4. (*second).getData() : 10
  5. Data(int data = 0)
  6. SecondLayer(Data* pData)
  7. ThirdLayer(SecondLayer* pSecond)
  8. third->getData() : 30
  9. third.operator->().operator->()->getData() : 30
  10. ~ThirdLayer()
  11. ~SecondLayer()
  12. ~Data()
  13. ~SecondLayer()
  14. ~Data()
复制代码


  • SecondLayer 答应访问 Data 对象。
  • ThirdLayer 答应访问 SecondLayer,终极可访问 Data。
  • 多层指针访问的署理模式收效,而且析构时正确开释了内存。

4. 总结

运算符作用实用场景返回值范例operator->()答应对象像指针一样访问成员智能指针、署理类指针或引用operator*()答应对象像指针一样解引用智能指针、署理类引用关键点:

  • operator->() 必要返回指针或引用,可以连续调用 ->。
  • operator*() 必要返回对象的引用,制止拷贝,进步性能。
  • 实用于封装指针的类,如智能指针和署理类。
本节学习了 成员访问运算符 -> 和 * 的重载,把握它们的用法可以更好地明白 智能指针 和 署理模式。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表