C++笔记之注册的含义

news2024/11/16 4:19:10

C++笔记之注册的含义

code review!

文章目录

  • C++笔记之注册的含义
    • 1.注册对象到Qt的信号槽系统中
    • 2.注册函数到Qt的元对象系统中
      • 元对象系统
        • 例1
        • 例2
    • 3.注册自定义类型到C++ STL容器中
    • 4.将函数指针传递给另一个类,注册回调函数
      • class ICallback存在的意义
      • 例1,用于说明ICallback类的作用
      • 例2,用于说明ICallback类的作用
      • 例3,用于说明ICallback类的作用
    • 5.下面回调函数的例程中哪一行代码是注册的动作?
    • 6.将C++类注册到QML中——qmlRegisterType
    • 7.将单个C++对象注册到QML上下文中——engine.rootContext()->setContextProperty
    • 8.上述两个例子中的“注册”的区别?

**在C++和Qt中,“注册”这个术语通常用于描述向系统或框架中添加或注册某些对象或函数的过程。**

在这里插入图片描述

1.注册对象到Qt的信号槽系统中

在这里插入图片描述

在上面的代码中,通过QObject::connect函数将QPushButton的clicked信号和MyClass的onButtonClicked槽函数连接起来,从而实现了回调函数的注册。

具体来说connect函数的:
第一个参数是发出信号的对象(即QPushButton对象)
第二个参数是信号的名称(即clicked)
第三个参数是接收信号的对象(即MyClass对象)
第四个参数是接收信号的函数名称(即onButtonClicked)

在这个过程中,我们将MyClass的onButtonClicked函数注册为了QPushButton的clicked信号的处理函数。因此,当按钮被点击时,QPushButton会发出clicked信号,MyClass就会接收到这个信号并调用onButtonClicked函数进行处理。这就是回调函数的注册过程

2.注册函数到Qt的元对象系统中

在这里插入图片描述

元对象系统

元对象系统(Meta-Object System)是Qt框架中的一个重要特性,它提供了一种机制,让Qt能够实现动态的对象间通信和数据传递。元对象系统在运行时通过使用元对象(Meta Object)来处理对象的属性、方法和信号等信息。

在Qt中,每个QObject派生类对象都有一个与之对应的元对象。元对象包含了QObject派生类对象的类型信息、属性信息、方法信息和信号槽信息等,这些信息可以在运行时被访问和修改。

元对象系统提供了一些特殊的宏,如Q_OBJECT宏、Q_PROPERTY宏、Q_SIGNALS宏和Q_SLOTS宏等,用于在定义QObject派生类时声明它们的属性、方法和信号槽等信息。在编译期间,这些宏会被预处理器翻译成相应的代码,生成元对象。

通过元对象系统,我们可以在运行时查询对象的属性和方法信息,也可以动态地设置和获取对象的属性值,调用对象的方法和信号槽等。这种机制使得Qt框架可以实现诸如对象反射、信号槽机制、动态调用和属性绑定等高级特性。

总之,元对象系统是Qt框架中非常重要的一个特性,为Qt提供了很多强大的功能和灵活性。

例1

在这里插入图片描述

这个程序中使用了元对象系统,具体表现在以下两点:

1.在 MyObject 类的定义中使用了 Q_OBJECT 宏。这个宏告诉编译器需要在 MyObject 类中添加一些代码,以支持元对象系统,比如添加元对象信息和信号槽机制。

2.在 main 函数中,使用了 QObject::connect 函数来连接信号和槽。这个函数可以根据参数中的函数指针获取信号和槽的元对象信息,并在运行时动态地建立连接关系,实现了信号槽机制。

例2

在这里插入图片描述

在这里插入图片描述

3.注册自定义类型到C++ STL容器中

在这里插入图片描述

“注册”一词通常用于描述向系统或框架中添加或注册某些对象或函数的过程。这个过程类似于我们在某些场合下需要向某些机构或组织注册自己的身份一样。

例如,在GUI编程中,当我们需要处理某个控件的事件时,我们需要向GUI库“注册”该控件的事件处理程序。这样,当事件发生时,GUI库就可以调用我们已经注册的事件处理程序函数来处理该事件。

在Qt中,当我们需要在运行时使用元对象系统来访问和操作某个类的成员时,我们需要使用Q_OBJECT宏将该类“注册”到元对象系统中。这样,我们就可以在运行时使用元对象系统来查询和修改该类的属性、调用该类的函数以及连接该类的信号和槽了。

因此,“注册”这个术语的含义是将某些对象或函数添加或注册到系统或框架中的过程,以便在需要时可以方便地访问和操作它们。

4.将函数指针传递给另一个类,注册回调函数

当我们在一个类中定义了一个回调函数时,我们需要将该函数注册到另一个类中。在这种情况下,“注册”是指将函数指针传递给另一个类,以便它可以在适当的时候调用该函数。下面是一个更详细的例子,它演示了如何使用注册回调函数:

假设我们正在编写一个GUI应用程序,并且需要在用户单击按钮时执行一些操作。为了实现这一点,我们可以定义一个按钮类Button,并在其中定义一个回调函数接口ICallback,该接口包含一个名为OnClick的方法。我们还需要定义一个具体的回调函数类ButtonClickHandler,它实现了ICallback接口,并在其中实现了OnClick方法。最后,我们将ButtonClickHandler对象的指针注册到Button对象中,以便在用户单击按钮时调用OnClick方法。
在这里插入图片描述

class ICallback存在的意义

在这个例子中,class ICallback存在的意义是为了定义一个回调函数接口。ICallback类是一个纯虚类,它只包含一个纯虚函数 OnClick(),这个函数没有具体的实现,需要由其派生类来实现。这个接口的作用是定义了一个规范,规定了回调函数的形式,使得各种不同的回调函数类都能够通过继承该接口来统一接口规范,从而能够被Button类所调用。

例1,用于说明ICallback类的作用

在这里插入图片描述

例2,用于说明ICallback类的作用

在这里插入图片描述

例3,用于说明ICallback类的作用

假设我们正在开发一个计算器程序,这个程序需要支持不同的计算器引擎,每个引擎可能有不同的计算方式,但是都需要提供一个统一的接口来获取计算结果。

为了实现这个功能,我们可以定义一个计算器引擎的接口类,这个类中定义了一个纯虚函数 Calculate(),用于计算表达式的值。然后,我们可以为不同的计算器引擎实现具体的计算方式,例如对于加法引擎,实现 Calculate() 函数时只需要对表达式中的两个数字进行相加操作。

接着,我们可以在程序中创建一个计算器对象,用于获取计算结果。在创建计算器对象时,我们可以指定使用哪种计算器引擎来计算表达式。在计算器对象需要计算表达式的时候,就可以调用引擎的 Calculate() 函数来获取计算结果。

在这个例子中,计算器引擎接口类就类似于ICallback类,它定义了一个规范,规定了计算器引擎的接口形式,使得不同的计算器引擎都能够继承该接口来实现自己的计算方式。而计算器对象则类似于Button类,它在需要计算表达式时,调用引擎的计算函数,从而实现了不同的计算方式。

假设我们有一个计算器程序,需要支持多种计算方式,例如基本的加减乘除,科学计算等。我们可以定义一个计算引擎接口,例如:

在这里插入图片描述

这个例子中,我们通过定义一个计算引擎接口,使得不同的计算器引擎都能够继承该接口来实现自己的计算方式。

class ICalculatorEngine {
public:
    virtual ~ICalculatorEngine() {}
    virtual double calculate(double num1, double num2) const = 0;
};

这个类只提供了一个成员函数 calculate 的声明,而没有提供任何数据成员或成员函数的定义。这是一种常见的设计模式,称为“接口类”或“纯虚函数类”,它的主要目的是定义一组接口或契约,而不是提供实现。

具体的计算器引擎可以继承这个接口类并实现 calculate 函数,以便实现自己的计算方式。通过这种方式,不同的计算器引擎都可以提供自己的实现,并且可以被客户端代码使用,而不需要知道具体实现的细节。这也符合面向对象设计中的开放封闭原则,即对扩展开放,对修改封闭。

需要注意的是,接口类中的虚函数通常应该声明为 const,以确保它们不会修改对象状态。同时,这个类的析构函数应该声明为虚函数,以确保正确释放子类对象的内存。

main函数可以正确运行,因为虚函数表在类的编译阶段就已经生成,并且在运行时动态地被加载和使用。在该代码中,每个引擎都实现了 calculate 纯虚函数,因此它们都可以被强制转换为 ICalculatorEngine 类型的指针,然后通过调用 calculate 函数进行计算。虚函数表是由编译器在编译期间生成的,不需要在运行时生成,因此即使类没有显式定义构造函数,也可以正常地创建和销毁类的实例。

5.下面回调函数的例程中哪一行代码是注册的动作?

#include <iostream>
#include <functional>

using Callback = std::function<void(int)>;

void performOperation(int data, Callback callback) {
    // 执行某些操作
    int result = data * 2;

    // 调用回调函数,通知处理结果
    callback(result);
}

void handleResult(int result) {
    std::cout << "Result: " << result << std::endl;
}

int main() {
    performOperation(100, handleResult);

    return 0;
}

在这里插入图片描述

6.将C++类注册到QML中——qmlRegisterType

在这里插入图片描述

7.将单个C++对象注册到QML上下文中——engine.rootContext()->setContextProperty

在这里插入图片描述
在这里插入图片描述

8.上述两个例子中的“注册”的区别?

在前面提到的两个例子中,都涉及将C++对象暴露给QML,但是它们的注册方式有一些区别。

  1. 将C++类注册到QML中:

    这个方法涉及将整个C++类注册到QML中,使得在QML中可以创建和使用该类的实例。这样做的目的是在QML中使用C++类的多个实例,而不仅仅是一个特定的实例。

    • 在C++中:你定义一个继承自QObject的类,其中包含你希望在QML中使用的方法和属性。然后在主要代码中,使用qmlRegisterType函数将这个类注册到QML模块中。

    • 在QML中:通过使用这个注册的类名,可以在QML中创建这个类的实例,并调用其方法和访问其属性。这种方法更适合于需要在QML中创建多个类实例的情况。

  2. 将单个C++对象注册到QML上下文中:

    这个方法涉及创建一个特定的C++对象,然后将该对象注册到QML上下文中,使得在QML中可以直接使用该对象的方法和属性。

    • 在C++中:你创建一个继承自QObject的类,然后在主要代码中创建一个类的实例,并将其通过上下文属性注册到QML上下文中。

    • 在QML中:通过使用注册的属性名,可以直接访问这个C++对象的方法和属性。这种方法适合于在QML中只需要使用一个特定的C++对象的情况。

总的来说,这两种方法的区别在于范围。第一种方法适用于在QML中使用多个类实例的情况,而第二种方法适用于在QML中只需要使用一个特定实例的情况。选择哪种方法取决于你的应用程序需求。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

专业课只考2门,计算机学硕最低分290的江苏院校

南京工业大学 考研难度&#xff08;☆&#xff09; 内容&#xff1a;23考情概况&#xff08;拟录取和复试分析&#xff09;、专业目录、23复试详情、各专业考情分析。 正文1332字&#xff0c;预计阅读&#xff1a;3分钟。 2023考情概况 南京工业大学计算机相关各专业复试和…

Intellij中直接运行ts配置:run configuration for typescript

在Intellij中可以借助插件run configuration for typescript直接运行typescript&#xff1a; run configuration for typescript插件本质还是依赖于 ts-node 来运行&#xff0c;只是其可以帮助我们自动配置好 ts-node 运行参数&#xff0c;简化使用。 第一步&#xff1a;安装…

uniapp配置添加阿里巴巴图标icon流程步骤

文章目录 下载复制文件到项目文件夹里项目配置目录结构显示图标 下载 阿里巴巴icon官网 https://www.iconfont.cn/ 复制文件到项目文件夹里 项目配置目录结构 显示图标

带你了解建堆的时间复杂度

目录 用向上调整建堆的时间复杂度 1.向上调整建堆的时间复杂度O(N*logN) 2.数学论证 3.相关代码 用向下调整建堆的时间复杂度 1.建堆的时间复杂度为O(N) 2.数学论证 3.相关代码 完结撒花✿✿ヽ(▽)ノ✿✿ 博主建议:面试的时候可能会被面试官问到建堆时间复杂度的证明过…

安卓手机的充电原理

安卓手机的充电原理是通过充电器将交流电转换为直流电&#xff0c;然后通过USB接口传输到手机电池中。手机电池的充电过程分为三个阶段&#xff1a;涓流充电、恒流充电和恒压充电。 充电动画 涓流充电是用来先对完全放电的电池单元进行预充&#xff08;恢复性充电&#xff09…

pdf 转 word

pdf 转 word 一、思路 直接调用LibreOffice 命令进行文档转换的命令行工具 使用的前系统中必须已经安装了 libreofficelibreoffice已翻译的用户界面语言包: 中文 (简体)libreoffice离线帮助文档: 中文 (简体)上传字体 重点&#xff1a;重点&#xff1a;重点&#xff1a; 亲…

蓝光眼镜有效吗?科研团队:无法证明防蓝光镜片可以减少视力伤害

8 月 19 日消息&#xff0c;本次由墨尔本大学、莫纳什大学和伦敦城市大学联合进行的科研团队&#xff0c;对来自 6个国家和地区的 17 项已发表的研究进行了深入研究。他们的研究发现&#xff0c;无法证明防蓝光镜片能够减少眼睛的视力伤害或改善佩戴者的睡眠质量等功效。 这项研…

【网络教程】如何获取阿里云盘的refresh_token

文章目录 获取阿里云盘的refresh_token 获取阿里云盘的refresh_token 这里在Edge浏览器上进行演示首先我们需要登入我们的阿里云盘然后按F12进入开发者模式&#xff0c;在菜单栏选择应用程序&#xff0c;然后在左边菜单找到 本地存储 下的 https://www.aliyundrive.com 这个域…

深入理解【二叉树】

&#x1f4d9;作者简介&#xff1a; 清水加冰&#xff0c;目前大二在读&#xff0c;正在学习C/C、Python、操作系统、数据库等。 &#x1f4d8;相关专栏&#xff1a;C语言初阶、C语言进阶、C语言刷题训练营、数据结构刷题训练营、有感兴趣的可以看一看。 欢迎点赞 &#x1f44d…

开发过程中自己遇到的异常(四)

mysql 报错&#xff1a;‘Lost connection to MySQL server during query 出现这种情况大多是因为&#xff0c;两个事物抢一个表的使用权造成的。 show processlist; 观察Command 列&#xff0c;有明显的update&#xff0c;insert, delete 时间比较久的&#xff0c;直接kill掉…

unity 之Transform组件(汇总)

文章目录 理论指导结合例子 理论指导 当在Unity中处理3D场景中的游戏对象时&#xff0c;Transform 组件是至关重要的组件之一。它管理了游戏对象的位置、旋转和缩放&#xff0c;并提供了许多方法来操纵和操作这些属性。以下是关于Transform 组件的详细介绍&#xff1a; 位置&a…

微服务系列文章之 SpringBoot 最佳实践

Spring Boot 是一种广泛使用且非常流行的企业级高性能框架。 以下是一些最佳实践和一些技巧&#xff0c;我们可以使用它们来改进 Spring Boot 应用程序并使其更加高效。 Spring Boot 的四大核心 1、自动配置 针对很多Spring应用程序和常见的应用功能&#xff0c;Spring Boo…

Linux 线程的概念与实现方式

一、线程的概念 线程是进程内部的一条执行序列或执行路径&#xff0c;一个进程可以包含多条线程。 一个进程中有两条或多条执行路径的时候&#xff0c;它们是可以同时执行的&#xff0c;也就是说&#xff0c;一个进程中的多个线程是可以同时执行的。当我们需要一个程序同时执行…

【LeetCode-简单题】49. 字母异位词分组

题目 题解一:排序哈希表 思路:由于互为字母异位词的两个字符串包含的字母相同&#xff0c;因此对两个字符串分别进行排序之后得到的字符串一定是相同的&#xff0c;故可以将排序之后的字符串作为哈希表的键。 核心api: //将字符串转换为字符数组char[] ch str.toCharArray();…

飞机打方块(二)游戏界面制作

一、背景 1.新建bg节点 二、飞机节点功能实现 1.移动 1.新建plane节点 2.新建脚本GameController.ts,并绑定Canvas GameControll.ts const { ccclass, property } cc._decorator;ccclass export default class NewClass extends cc.Component {property(cc.Node)canvas:…

详解strcmp函数

strcmp函数是用来比较两个字符串的&#xff0c;按理来说&#xff0c;比较结果只有两种&#xff1a;相同或不同。但是&#xff0c;事实上&#xff0c;strcmp函数在设计时会有三种情况&#xff0c;下面详细介绍&#xff1a; 这个函数的输入为两个字符串的首元素地址&#xff08;即…

Hlang--用Python写个编程语言-逻辑运算

文章目录 前言关键词解析token解析器解释器语法表示前言 在上一篇文章里面,实现了基本的变量,并且详细地阐述了基本原理,所以的话,这里要实现的就是这个判断,由于架子基本上打好了,后面的操作无法就是确定这个AST的一个执行顺序,也就是我们希望解释器执行的一个情况。 …

OpenCV基础知识(5)— 几何变换

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。OpenCV中的几何变换是指改变图像的几何结构&#xff0c;例如大小、角度和形状等&#xff0c;让图像呈现出缩放、翻转、旋转和透视效果。这些几何变换操作都涉及复杂、精密的计算。OpenCV将这些计算过程都封装成了非常灵活的…

8. 实现业务功能--用户注册

目录 1. 顺序图 2. 参数要求 3. 接口规范 4. 创建扩展 Mapper.xml 5. 修改 DAO 6. 创建 Service 接口 7. 实现接口 8. 测试接口 9. 实现 Controller 9.1 密码加密处理 10. 实现前端界面 业务实现过程中主要的包和目录及主要功能&#xff1a; model 包&#xff1a;实体对象 d…

一文带你了解G1收集器:全功能的垃圾收集器

&#xff08;笔记参考书籍&#xff1a;《JVM高级特性与最佳实践》&#xff09; 一、介绍 Garbage First&#xff08;简称G1&#xff09;收集器是垃圾收集器技术发展历史上的里程碑式的成果&#xff0c;它开创了收集器面向局部收集的设计思路和基于Region的内存布局形式。 G1…