C++11QT复习 (五)

embedded/2025/3/26 5:35:08/

文章目录

    • **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->,使得用户无需手动解引用即可访问目标对象的成员。

注意事项:

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

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

(1) 语法
class A {
public:B& operator*();
};

作用

  • 允许 A 类的对象 像指针一样进行解引用
  • 常见于智能指针的实现,使 *ptr 直接返回对象的引用,方便访问其成员。

注意事项:

  1. 返回值一般是引用(如 B&),这样不会产生额外的拷贝。
  2. 适用于 封装指针 的类,如智能指针或代理类。

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*()允许对象像指针一样解引用智能指针、代理类引用

关键点:

  1. operator->() 需要返回指针或引用,可以连续调用 ->
  2. operator*() 需要返回对象的引用,避免拷贝,提高性能。
  3. 适用于封装指针的类,如智能指针和代理类

本节学习了 成员访问运算符 ->* 的重载,掌握它们的用法可以更好地理解 智能指针代理模式


http://www.ppmy.cn/embedded/176708.html

相关文章

吾爱出品,文件分类助手,高效管理您的 PC 资源库

在日常使用电脑的过程中&#xff0c;文件杂乱无章常常让人感到困扰。无论是桌面堆积如山的快捷方式&#xff0c;还是硬盘中混乱的音频、视频、文档等资源&#xff0c;都急需一种高效的整理方法。文件分类助手应运而生&#xff0c;它是一款文件管理工具&#xff0c;能够快速、智…

Cmake创建一个QML

使用Qt Quick module.创建一个 QML demo cmake_minimum_required(VERSION 3.16)project(hello VERSION 1.0 LANGUAGES CXX)find_package(Qt6 6.3 COMPONENTS Quick Gui REQUIRED)qt_standard_project_setup(REQUIRES 6.5) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_…

基于Java的班级事务管理系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 随着世界经济信息化、全球化的到来和电子商务的飞速发展&#xff0c;推动了很多行业的改革。若想达到安全&#xff0c;快捷的目的&#xff0c;就需要拥有信息化的组织和管理模式&#xff0c;建立一套合理、畅通、高效的线上管理系统。当前的班级事务管理存在管理效率低下…

《K230 从熟悉到...》边缘检测

《K230 从熟悉到...》边缘检测 Candy简单的阈值高通滤波算法拉普拉斯核 《庐山派 K230 从熟悉到...》边缘检测 Canny和阈值高通滤波用的同一个API&#xff0c;只在参数中做区别。 Candy img.find_edges(image.EDGE_CANNY, threshold(50, 80))简单的阈值高通滤波算法 img.find…

VC++重绘CheckBox,方便直接可以用

记得关注! #include "stdafx.h" #include "CCheckSK.h" CCheckSK::CCheckSK() { m_bCheck = FALSE; m_bMouseOver = FALSE; m_nLedSize = 15; // set default color to green on ON and dark-green on OFF //m_colLedOn = RGB(0, 255, 0)…

运用scipy库进行线性拟合

一、概述 此代码运用 Python 的numpy、matplotlib和scipy库&#xff0c;完成对带噪声线性数据的线性模型拟合与可视化。具体步骤为定义线性模型函数&#xff0c;生成带有噪声的线性数据&#xff0c;利用curve_fit函数进行数据拟合&#xff0c;最后借助matplotlib库将原始数据与…

Qt 隐式共享

隐性共享 Qt 中的许多 C 类都使用隐式数据共享&#xff0c;以最大限度地提高资源利用率并减少复制。隐式共享类在作为参数传递时既安全又高效&#xff0c;因为只传递指向数据的指针&#xff0c;只有在函数写入数据时才复制数据&#xff0c;即写时复制。 概述 共享类由指向共…

java+selenium(资源全备,打开已使用浏览器信息,保留用户信息)

javaselenium(资源全备&#xff0c;打开已使用浏览器信息&#xff0c;保留用户信息) 一、介绍 我的代码可以实现以下效果&#xff1a; 保留用户信息&#xff0c;好处&#xff1a;可以在登录好一个账号后还保留原来的token验证信息 使用javaselenium实现爬取vue元素内容&…