C++笔记之注册的含义

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.mzph.cn/news/47765.shtml

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

相关文章

Python Opencv实践 - 图像中值滤波

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR) print(img.shape) pixel_count img.shape[0] * img.shape[1] print(pixel_count)#为图像添加椒盐噪声 #参考资料&#xf…

Java中异常的详细讲解与细节讨论

用一个代码引出异常为什么要使用异常 代码&#xff1a; public static void main(Sting args[]){int n1 1;int n2 0;System.out.println(n1/n2);//这里会抛ArihmaticException,因为除数不能为0,若未用异常处理机制则程序直接结束&#xff0c;后面的代码将不执行。这样很不好…

windows ipv4 多ip地址设置,默认网关跃点和自动跃点是什么意思?(跃点数)

文章目录 Windows中的IPv4多IP地址设置以及默认网关跃点和自动跃点的含义引言IPv4和IPv6&#xff1a;简介多IP地址设置&#xff1a;Windows环境中的实现默认网关跃点&#xff1a;概念和作用自动跃点&#xff1a;何时使用&#xff1f;关于“跃点数”如何确定应该设置多少跃点数&…

我的创作纪念日(C++修仙练气期总结)

分享自己最喜欢的一首歌&#xff1a;空想フォレスト—伊東歌詞太郎 机缘 现在想想自己在CSDN创作的原因&#xff0c;一开始其实就是想着拿着博客当做自己的学习笔记&#xff0c;笔记嘛&#xff0c;随便写写&#xff0c;自己看得懂就ok了的态度凸(艹皿艹 )。也是用来作为自己学习…

vue3+element下拉多选框组件

<!-- 下拉多选 --> <template><div class"select-checked"><el-select v-model"selected" :class"{ all: optionsAll, hidden: selectedOptions.data.length < 2 }" multipleplaceholder"请选择" :popper-app…

vite 项目搭建

1. 创建 vite 项目 npm create vite@latest 2. 安装sass/less ( 一般我使用sass ) cnpm add -D sasscnpm add -D less 3. 自动导入 两个插件 使用之后,不用导入vue中hook reactive ref cnpm install -D unplugin-vue-components unplugin-auto-import 在 vite.config.…

STM32设置为I2C从机模式(HAL库版本)

STM32设置为I2C从机模式&#xff08;HAL库版本&#xff09; 目录 STM32设置为I2C从机模式&#xff08;HAL库版本&#xff09;前言1 硬件连接2 软件编程2.1 步骤分解2.2 测试用例 3 运行测试3.1 I2C连续写入3.2 I2C连续读取3.3 I2C单次读写测试 4 总结 前言 我之前出过一篇关于…

Claude 2 国内镜像站

Claudeai是什么&#xff1f; Claude 2被称为ChatGPT最强劲的竞争对手&#xff0c;支持100K上下文对话&#xff0c;并且可以同时和5个文档进行对话&#xff0c;不过国内目前无法正常实用的&#xff0c;而claudeai是一个Claude 2 国内镜像站&#xff0c;并且免翻可用&#xff0…

实验三 HBase1.2.6安装及配置

系列文章目录 文章目录 系列文章目录前言一、HBase1.2.6的安装二、HBase1.2.6的配置2.1 单机模式配置2.2 伪分布式模式配置 总结参考 前言 在安装HBase1.2.6之前&#xff0c;需要安装好hadoop2.7.6。 本篇文章参考&#xff1a;HBase2.2.2安装和编程实践指南 一、HBase1.2.6的安…

Android---- 一个完整的小项目(消防app)

前言&#xff1a; 针对不同群体的需求&#xff0c;想着应该拓展写方向。医疗app很受大家喜欢&#xff0c;就打算顺手写个消防app&#xff0c;里面基础框架还是挺简洁 规整的。登陆注册和本地数据库写的便于大家理解。是广大学子的毕设首选啊&#xff01; 此app主要为了传递 消防…

代码随想录打卡—day24—【回溯】— 基础最新8.20+8.22

1 理论基础 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。回溯算法——回溯和递归是相辅相成的。回溯法的效率&#xff0c;回溯法其实就是暴力查找&#xff0c;并不是什么高效的算法。回溯法解决的问题都可以抽象为树形结构&#xff08;N叉树&#xff09; 1.1…

redis 7高级篇1 redis的单线程与多线程

一 redis单线程与多线程 1.1 redis单线程&多线程 1.redis的单线程 redis单线程主要是指Redis的网络IO和键值对读写是由一个线程来完成的&#xff0c;Redis在处理客户端的请求时包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理…

【第三阶段】kotlin语言的内置函数let

1.使用普通方法对集合的第一个元素相加 fun main() {//使用普通方法对集合的第一个元素相加var list listOf(1,2,3,4,5)var value1list.first()var resultvalue1value1println(result) }执行结果 2.使用let内置函数对集合的第一个元素相加 package Stage3fun main() {//使用…

Android进阶之路 - 去除EditText内边距

正如题名&#xff0c;在Android中的EditText是自带内边距的&#xff0c;常规而言设置背景为null即可&#xff0c;但是因为使用了并不熟悉的声明式框架&#xff0c;本是几分钟解决的事儿&#xff0c;却花费了小半天~ 简单的需求&#xff0c;相关blog Android进阶之路 - 去除Edi…

探索智能文字识别:技术、应用与发展前景

探索智能文字识别&#xff1a;技术、应用与发展前景 前言一张图全览大赛作品解读随心记你不对我对小结 智能文字识别体系化解读图像预处理文字定位和分割文字区域识别图像校正字体识别和匹配结果后处理小结 如何应对复杂场景下挑战复杂场景应对方法小结 人才时代对人才要求合合…

MyBatis快速入门以及环境搭建和CRUD的实现

目录 前言 一、MyBatis简介 1.MyBatis是什么 2.MyBatis的特点 3.mybatis的作用 4.MyBatis的应用场景 5.MyBatis优缺点 二、相关概念 1.ORM概述 2.常见的ORM框架 3.什么是持久层框架 三、MyBatis的工作原理 1.框架交互 2.工作原理 ​编辑 四、MyBatis环境搭建 1…

Linux Kernel 4.12 或将新增优化分析工具

到 7 月初&#xff0c;Linux Kernel 4.12 预计将为修复所有安全漏洞而奠定基础&#xff0c;另外新增的是一个分析工具&#xff0c;对于开发者优化启动时间时会有所帮助。 新的「个别任务统一模型」&#xff08;Per-Task Consistency Model&#xff09;为主要核心实时修补&#…

软件开发之低代码平台实践

一、低代码、零代码、纯代码定义 低代码开发平台使企业在不编写大量代码的情况下快速创建复杂应用程序。与传统的纯代码开发相比&#xff0c;低代码开发能够大大减少开发周期&#xff0c;并降低技术门槛&#xff0c;使得开发过程更加高效。而零代码开发更进一步简化了开发过程&…

C++信息学奥赛1121:计算矩阵边缘元素之和

题解&#xff1a;i0 or j0 or in-1 or jm-1 or in-1 or jm-1 代码&#xff1a; #include<iostream> // 包含输入输出流库 #include<cmath> // 包含数学函数库 using namespace std; // 使用标准命名空间int main() {int n,m;cin>>n>>m; // 输入…

【Java从0到1学习】10 Java常用类汇总

1. System类 System类对读者来说并不陌生&#xff0c;因为在之前所学知识中&#xff0c;需要打印结果时&#xff0c;使用的都是“System.out.println();”语句&#xff0c;这句代码中就使用了System类。System类定义了一些与系统相关的属性和方法&#xff0c;它所提供的属性和…