C++ QT中Q_Q和Q_D是什么?怎么使用?本质是什么?C++仿写

1.QT中Q_Q和Q_D是什么?

  • Q_Q可以得到外部可以访问的类指针
  • Q_D可以得到内部封装,外部不可达的类指针

2. 怎么使用?

上代码

  • APrivate.h
#pragma once
#include <QtCore>

class A;

class APrivate
{
	Q_DECLARE_PUBLIC(A)
public:
	APrivate();
	~APrivate();
public:
	void APrivateUseA();
private:
	friend A;
	A* q_ptr;
	int m_iA;
};
  • A.h
#pragma once
#include <QtCore>
class APrivate;

class A
{
	Q_DECLARE_PRIVATE(A)
public:
	A();
	~A();

public://对外接口
	void setValue(int& iValue);
	int getValue();

public:
	void APrivateCanUse();
	void APrivateUse();

private:
	APrivate* d_ptr;
};
  • A.cpp
#include "APrivate.h"
#include "A.h"
#include <iostream>

A::A():d_ptr(new APrivate) 
{
	d_ptr->q_ptr = this;
	std::cout << "A()" << std::endl;
}
A::~A() 
{
	Q_D(A);
	delete d;
	std::cout << "~A()" << std::endl;
}

void A::setValue(int& iValue)
{
	Q_D(A);
	d->m_iA = iValue;
}

int A::getValue()
{
	Q_D(A);
	return d->m_iA;
}

void A::APrivateCanUse()
{
	int iValue = 3;
	setValue(iValue);
}

void A::APrivateUse()
{
	Q_D(A);
	d->APrivateUseA();
}

APrivate::APrivate():m_iA(1)
{
	std::cout << "APrivate()" << std::endl;
}
APrivate::~APrivate() 
{
	std::cout << "~APrivate()" << std::endl;
}

void APrivate::APrivateUseA()
{
	Q_Q(A);
	q->APrivateCanUse();
}
  • main.cpp使用
#include <QtCore/QCoreApplication>
#include <iostream>
#include "A.h"
#include "APrivate.h"
#include <memory>

int main(int argc, char* argv[])
{
	QCoreApplication a(argc, argv);
	{	
		//1
		std::unique_ptr<A> Aa = std::make_unique<A>();
		std::cout << Aa->getValue() << std::endl;
		//2
		int Value = 2;
		Aa->setValue(Value);
		std::cout << Aa->getValue() << std::endl;
		//3
		Aa->APrivateUse();
		std::cout << Aa->getValue() << std::endl;

	}
	return a.exec();
}

输出:

APrivate()
A()
1
2
3
~APrivate()
~A()

3.本质是什么?

  • 详见QtCore文件夹下文的头文件qglobal.h
  • 摘录主要部分如下:
template <typename T> inline T *qGetPtrHelper(T *ptr) { return ptr; }
template <typename Ptr> inline auto qGetPtrHelper(Ptr &ptr) -> decltype(ptr.operator->()) { return ptr.operator->(); }

// The body must be a statement:
#define Q_CAST_IGNORE_ALIGN(body) QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wcast-align") body QT_WARNING_POP
#define Q_DECLARE_PRIVATE(Class) \
    inline Class##Private* d_func() \
    { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr));) } \
    inline const Class##Private* d_func() const \
    { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));) } \
    friend class Class##Private;

#define Q_DECLARE_PRIVATE_D(Dptr, Class) \
    inline Class##Private* d_func() \
    { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(Dptr));) } \
    inline const Class##Private* d_func() const \
    { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(Dptr));) } \
    friend class Class##Private;

#define Q_DECLARE_PUBLIC(Class)                                    \
    inline Class* q_func() { return static_cast<Class *>(q_ptr); } \
    inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } \
    friend class Class;

#define Q_D(Class) Class##Private * const d = d_func()
#define Q_Q(Class) Class * const q = q_func()
  • 为了方便理解裁剪代码如下:(对照步骤2如何使用来理解)
template <typename T> inline T *qGetPtrHelper(T *ptr) { return ptr; }
//A.h中的声明,Class为A
#define Q_DECLARE_PRIVATE(Class) \
    inline Class##Private* d_func() \
    {return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } \
    inline const Class##Private* d_func() const \
    {return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));} \
    friend class Class##Private;
//APrivate.h中的声明,Class为A
#define Q_DECLARE_PUBLIC(Class)                                    \
    inline Class* q_func() { return static_cast<Class *>(q_ptr); } \
    inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } \
    friend class Class;
//使用时的声明,取得临时指针
#define Q_D(Class) Class##Private * const d = d_func()
#define Q_Q(Class) Class * const q = q_func()

评论:

优:风格统一,使用便捷

劣:每次使用都要两个指针2*8=16个字节的额外开销

4.仿写

不用QT库,C++仿写

  • BPrivate.h
#pragma once
class B;

class BPrivate
{
public:
	BPrivate();
	~BPrivate();
public:
	void BPrivateUseB();
private:
	friend B;
	B* q_ptr;
	int m_iA;
};
  • B.h
#pragma once
class BPrivate;

class B
{
public:
	B();
	~B();

public://对外接口
	void setValue(int& iValue);
	int getValue();

public:
	void BPrivateCanUse();
	void BPrivateUse();

private:
	BPrivate* d_ptr;
};
  • B.cpp
#include "BPrivate.h"
#include "B.h"
#include <iostream>

B::B() :d_ptr(new BPrivate)
{
	d_ptr->q_ptr = this;
	std::cout << "B()" << std::endl;
}
B::~B()
{
	delete d_ptr;
	std::cout << "~B()" << std::endl;
}

void B::setValue(int& iValue)
{
	d_ptr->m_iA = iValue;
}

int B::getValue()
{
	return d_ptr->m_iA;
}

void B::BPrivateCanUse()
{
	int iValue = 3;
	setValue(iValue);
}

void B::BPrivateUse()
{
	d_ptr->BPrivateUseB();
}

BPrivate::BPrivate() :m_iA(1)
{
	std::cout << "BPrivate()" << std::endl;
}
BPrivate::~BPrivate()
{
	std::cout << "~BPrivate()" << std::endl;
}

void BPrivate::BPrivateUseB()
{
	q_ptr->BPrivateCanUse();
}
  • main.cpp
#include <QtCore/QCoreApplication>
#include <iostream>
#include "A.h"
#include "APrivate.h"
#include "B.h"
#include "BPrivate.h"
#include <memory>

int main(int argc, char* argv[])
{
	QCoreApplication a(argc, argv);
	{	
		//1
		std::unique_ptr<A> Aa = std::make_unique<A>();
		std::cout << Aa->getValue() << std::endl;
		//2
		int Value = 2;
		Aa->setValue(Value);
		std::cout << Aa->getValue() << std::endl;
		//3
		Aa->APrivateUse();
		std::cout << Aa->getValue() << std::endl;
	}

	{
		//1
		std::unique_ptr<B> Bb = std::make_unique<B>();
		std::cout << Bb->getValue() << std::endl;
		//2
		int Value = 2;
		Bb->setValue(Value);
		std::cout << Bb->getValue() << std::endl;
		//3
		Bb->BPrivateUse();
		std::cout << Bb->getValue() << std::endl;
	}
	return a.exec();
}
  • 输出(一样):
APrivate()
A()
1
2
3
~APrivate()
~A()
BPrivate()
B()
1
2
3
~BPrivate()
~B()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/955384.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

三种文本相似计算方法:规则、向量与大模型裁判

文本相似计算 项目背景 目前有众多工作需要评估字符串之间的相似(相关)程度&#xff1a;  比如&#xff0c;RAG 智能问答系统文本召回阶段需要计算用户文本与文本库内文本的相似分数&#xff0c;返回前TopK个候选文本。  在评估大模型生成的文本阶段&#xff0c;也需要评估…

高效实现 Markdown 转 PDF 的跨平台指南20250117

高效实现 Markdown 转 PDF 的跨平台指南 引言 Markdown 文件以其轻量化和灵活性受到开发者和技术写作者的青睐&#xff0c;但如何将其转换为易于分享和打印的 PDF 格式&#xff0c;是一个常见需求。本文整合了 macOS、Windows 和 Linux 三大平台的转换方法&#xff0c;并探讨…

浅谈云计算21 | Docker容器技术

Docker容器技术 一、 容器技术特性1.1 轻量级特性1.2 隔离性特性 二、容器镜像2.1 容器镜像概述2.1.1 定义与构成2.1.2 分层结构 2.2 联合文件系统2.3 容器镜像的构建与管理2.3.1 容器镜像的构建2.3.2 **构建镜像流程**2.3.3 **应用场景**2.3.4 镜像仓库的应用 2.4 容器镜像的优…

LabVIEW实现油浸式变压器自主监测与实时报告

油浸式变压器广泛应用于电力系统中&#xff0c;尤其是在电力传输和分配领域。为了确保变压器的安全、稳定运行&#xff0c;及时监测其工作状态至关重要。传统的变压器监测方法通常依赖人工巡检和定期检查&#xff0c;但这不能及时发现潜在的故障隐患&#xff0c;且效率较低。随…

【2025最新】国内中文版 ChatGPT镜像网站整理合集,GPT最新模型4o1,4o,4o-mini分类区别,镜像站是什么

1.快速导航 原生中转型镜像站点 立即Chat支持GPT4、4o以及o1,canvs等&#xff0c;同步官网功能 AIChat.com 支持最新4O 2.两者对比 官网立即Chat访问难度需要魔法直接访问支付手段国际支付国内支付封禁策略检测节点&#xff0c;随时封禁不会封禁价格每月140元订阅费用每年70元…

SpringBoot:RestTemplate与IllegalArgumentException

问题描述 在SpringBoot应用中&#xff0c;有时会遇到使用RestTemplate调用第三方服务的场景。例如&#xff1a;在进行地名数据采集时&#xff0c;为了拿到地名对应的经纬度位置&#xff0c;通常会有地理编码的步骤&#xff0c;此时就可能涉及到调用第三方接口服务实现此需求。 …

【日志篇】(7.6) ❀ 01. 在macOS下刷新FortiAnalyzer固件 ❀ FortiAnalyzer 日志分析

【简介】FortiAnalyzer 是 Fortinet Security Fabric 安全架构的基础&#xff0c;提供集中日志记录和分析&#xff0c;以及端到端可见性。因此&#xff0c;分析师可以更有效地管理安全状态&#xff0c;将安全流程自动化&#xff0c;并快速响应威胁。具有分析和自动化功能的集成…

HTML中如何保留字符串的空白符和换行符号的效果

有个字符串 储值门店{{thing3.DATA}}\n储值卡号{{character_string1.DATA}}\n储值金额{{amount4.DATA}}\n当前余额{{amount5.DATA}}\n储值时间{{time2.DATA}} &#xff0c; HTML中想要保留 \n的换行效果的有下面3种方法&#xff1a; 1、style 中 设置 white-space: pre-lin…

【腾讯云】AI驱动TDSQL-C Serveress 数据库技术实战营-如何是从0到1体验电商可视化分析小助手得统计功能,一句话就能输出目标统计图

欢迎来到《小5讲堂》 这是《腾讯云》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 背景效果图流程图创建数据库 基本信息数据库配置设置密码控制台开…

基于预共享密钥的IPsec实验

一、实验目的 &#xff08;1&#xff09;了解IPsec的原理和协议运行机制&#xff1b; &#xff08;2&#xff09;掌握IPsec身份认证的预共享密钥的配置&#xff1b; &#xff08;3&#xff09;掌握用Wireshark工具抓包分析IPsec数据包格式和协议流程。 二、实验设备与环境 &…

微信小程序实现个人中心页面

文章目录 1. 官方文档教程2. 编写静态页面3. 关于作者其它项目视频教程介绍 1. 官方文档教程 https://developers.weixin.qq.com/miniprogram/dev/framework/ 2. 编写静态页面 mine.wxml布局文件 <!--index.wxml--> <navigation-bar title"个人中心" ba…

初学stm32 --- flash模仿eeprom

目录 STM32内部FLASH简介 内部FLASH构成&#xff08;F1&#xff09; FLASH读写过程&#xff08;F1&#xff09; 闪存的读取 闪存的写入 内部FLASH构成&#xff08;F4 / F7 / H7&#xff09; FLASH读写过程&#xff08;F4 / F7 / H7&#xff09; 闪存的读取 闪存的写入 …

Kinova仿生机械臂Gen3搭载BOTA 力矩传感器SeneOne:彰显机器人触觉 AI 与六维力传感的融合力量

随着工业4.0时代的到来&#xff0c;自动化和智能化成为制造业的趋势。机器人作为实现这一趋势的重要工具&#xff0c;其性能和智能水平直接影响到生产效率和产品质量。然而&#xff0c;传统的机器人系统在应对复杂任务时往往缺乏足够的灵活性和适应性。为了解决这一问题&#x…

浅谈计算机网络03 | 现代网络组成

现代网络组成 一 、网络生态体系1.1网络生态系统的多元主体1.2 网络接入设施的多样类型 二、现代网络的典型体系结构解析三、高速网络技术3.1 以太网技术3.2 Wi-Fi技术的深度剖析3.2.1 应用场景的多元覆盖3.2.2 标准升级与性能提升 3.3 4G/5G蜂窝网的技术演进3.3.1 蜂窝技术的代…

电子画册制作平台哪个好?

​作为一个热爱分享的人&#xff0c;我试过了好几个平台&#xff0c;终于找到了几款比较好用得电子杂志制作平台&#xff0c;都是操作界面很简洁&#xff0c;上手非常快的工具。 FLBOOK:这是一款在线制作H5电子画册软件&#xff0c;提供了各种类型的模板&#xff0c;可支持添加…

如何在 Google Cloud Shell 中使用 Visual Studio Code (VS Code)?

Google Cloud Shell 是一个基于浏览器的命令行界面&#xff0c;它提供了一个临时的虚拟机环境&#xff0c;允许开发者在没有本地环境配置的情况下使用 Google Cloud 的各种服务。它还提供了一个免费的 5GB 存储空间以及可以在其中执行所有 Google Cloud 操作的命令行界面。 Vis…

anaconda安装和环境配置

文章目录 一、Anaconda下载1.从官网直接下载&#xff1a;2.从镜像站中下载&#xff1a; 二、Anaconda安装三、检测是否有Anaconda配置anaconda环境 四、 Anaconda创建多个python环境&#xff08;方便管理项目环境&#xff09;1.查看conda有哪些环境2.创建python3.6的环境3.激活…

CF 641A.Little Artem and Grasshopper(Java实现)

题目分析 蚂蚱会在n个房间中根据既定房间规则向固定方向跳跃固定长度&#xff0c;试问是否能够跳出这个长度&#xff08;即落点位置在0或n1&#xff09; 思路分析 输入n就有n个房间&#xff0c;n套规则&#xff08;固定方向和跳跃距离&#xff09;&#xff0c;蚂蚱到哪个房间就…

css 实现自定义虚线

需求&#xff1a; ui 画的图是虚线&#xff0c;但是虚线很宽正常的border 参数无法做到 进程&#xff1a; 尝试使用 border&#xff1a;1px dashed 发现使用这个虽然是虚线但是很短密密麻麻的 这并不是我们想要的那就只能换方案 第一个最简单&#xff0c;让ui 画一个图然…

Bottleneck层模型介绍

瓶颈设计的思想是引入一个瓶颈层&#xff0c;它由一系列不同大小的滤波器组成&#xff0c;通常是1x1、3x3和1x1的卷积层序列&#xff1a;第一个1x1卷积层&#xff1a;用于减少通道数&#xff0c;即降维&#xff0c;从而降低计算复杂度。 3x3卷积层&#xff1a;用于提取空间特征…