C++ 类和对象(一)

目录

0.前言

1.面向过程&面向对象

1.1面向过程编程(PP)

1.2面向对象编程(OOP)

1.3从C到C++

2.类的引入

2.1C语言中的结构体

2.2C++中类的引入

2.3结构体与类的区别

2.4为什么引入类

3.类的定义

3.1声明与定义不分离

3.2声明与定义分离

3.3如何选择

4.类的访问限定符与封装

4.1访问限定符

4.2封装

5.类的作用域

6.类的实例化

6.1概念

6.2实例化方式

7.类成员的储存

7.1计算类对象的大小

7.2类对象的储存方式

7.2.1成员变量的储存

7.2.2成员函数的储存

7.3类/结构体内存对齐

7.3.1内存对齐的基本规则

8.this指针

8.1概述

8.2为什么引入this指针

8.3this指针的特性

9.小结


(图像由AI生成) 

0.前言

在计算机编程的世界里,语言的演进是为了更好地适应开发的需要,提高软件的质量和开发效率。C++作为一种高效的编程语言,它在C语言的基础上增加了面向对象的特性。这篇博客将带你了解C++中类和对象的基础知识,为你打开面向对象编程的大门。

1.面向过程&面向对象

当我们从学习C语言转向学习C++时,我们实际上是在从面向过程编程(Procedural Programming, PP)迈向面向对象编程(Object-Oriented Programming, OOP)。这两种编程范式在处理复杂性、代码组织和重用方面有着根本的不同。

1.1面向过程编程(PP)

面向过程编程是一种以过程(函数)为中心的编程范式,强调的是“做什么”和“如何做”。在C语言中,程序被视为一系列的函数调用。数据和函数是分开的,数据定义在函数外部,而函数则操作这些数据。这种方式在处理简单任务时非常有效,因为它允许程序员以线性方式思考问题。

  • 优点:对于小型程序和简单问题,面向过程的方法可以快速地提供解决方案,因为它允许直接操作数据和使用简单的逻辑。
  • 缺点:随着程序的增长,面向过程的代码可能变得难以维护和扩展。全局数据的使用可能导致数据被错误地修改,而代码的重用也变得更加困难。

1.2面向对象编程(OOP)

面向对象编程则是一种以对象为中心的编程范式,强调“是什么”和“能做什么”。在C++中,对象是数据和操作这些数据的函数(称为方法)的封装体。OOP通过封装(Encapsulation)、继承(Inheritance)和多态性(Polymorphism)来增加代码的重用性、灵活性和可维护性。

  • 封装:封装是将数据(属性)和操作数据的代码(方法)捆绑在一起的过程,这样可以隐藏对象的实际实现细节,仅通过定义好的接口与对象交互。

  • 继承:继承允许我们定义一个基类(父类)的属性和方法,然后通过派生更具体的子类来扩展或修改这些功能。这促进了代码的重用和扩展性。

  • 多态性:多态性是指允许我们用一个统一的接口来操作不同类型的对象,具体操作依赖于对象的实际类型。这使得我们可以编写更通用和灵活的代码。

  • 优点:OOP使得程序更易于理解、维护和扩展。通过对象的封装,可以更好地管理和保护数据。继承和多态性进一步提高了代码的重用性和灵活性。

  • 缺点:面向对象的设计和实现通常比面向过程更复杂,可能需要更多的时间来学习和掌握。对于一些简单的问题,使用OOP可能会导致过度设计。

1.3从C到C++

当我们从C语言转向C++学习时,实际上是在学习如何以一种更抽象的方式思考问题。我们需要开始考虑如何将问题域内的概念建模为对象,这些对象如何相互交互,以及如何通过继承和多态性来组织和简化代码。尽管这种转变最初可能会挑战我们的思维习惯,但随着时间的推移,我们将发现面向对象的方法能够更自然地映射复杂的问题和现实世界的结构。

2.类的引入

在理解C++类的引入之前,我们首先要看看C语言中的结构体(struct),因为它为类的概念奠定了基础。

2.1C语言中的结构体

C语言允许我们通过结构体来定义和组织不同类型的数据。结构体是一种复合数据类型,它使得我们能够将多个不同类型的变量组合成一个单一的单位。例如,如果我们想要存储一个人的信息,包括名字、年龄和身高,我们可以这样定义一个结构体:

struct Person {char name[50];int age;float height;
};

结构体帮助我们在C语言中实现了数据的初步“封装”,但它的功能还是相对有限。结构体主要用于数据的存储,而对于数据的操作,则仍然依赖于外部的函数。

2.2C++中类的引入

C++在结构体的基础上引入了类(class),这是面向对象编程的核心。类不仅包括数据成员(即属性),还包括成员函数(即方法),这使得数据和操作数据的逻辑能够被封装在一起。这种封装性是OOP的一个重要特性,它提高了代码的复用性和可维护性。

使用C++类,我们可以这样重写上面的例子:

class Person {
public:char name[50];int age;float height;void printInfo() {std::cout << "Name: " << name << ", Age: " << age << ", Height: " << height << std::endl;}
};

在这个类的定义中,printInfo是一个成员函数,它与结构体内部的数据紧密相关,可以直接访问和操作这些数据。与C语言的结构体相比,C++的类提供了更高级的数据抽象和封装能力。

2.3结构体与类的区别

在C++中,结构体和类非常相似,事实上,它们之间的主要区别在于默认的访问权限:类的成员默认是private的,而结构体的成员默认是public的。这意味着,除非显式指定,否则类的数据成员和成员函数在类的外部是不可访问的,这强化了封装性。

2.4为什么引入类

引入类的目的是为了更好地支持抽象和封装,这是面向对象编程的核心概念之一。通过将数据和操作数据的逻辑捆绑在一起,类使得开发者能够创建更加复杂和高级的数据结构,这些数据结构不仅能够存储数据,还能够定义与数据相关的操作。这种方式大大提高了代码的重用性和可维护性,是从结构化编程向面向对象编程转变的一个重要步骤。

3.类的定义

在C++中,定义类是建立对象模板的基础步骤,涉及到成员变量(属性)和成员函数(方法)的声明及定义。C++提供两种主流的类定义方法:声明与定义不分离与声明与定义分离。

3.1声明与定义不分离

这种方法将类的声明和定义放置在同一位置,通常适用于简单的类定义。在这个方法中,类的成员函数直接在类定义内部实现。例如:

class Box {
public:double length; // 长度double width;  // 宽度double height; // 高度double getVolume() {return length * width * height; // 计算体积}
};

这里,Box类直接在其声明中定义了getVolume函数。

3.2声明与定义分离

对于更复杂的类,通常采用声明与定义分离的方式。这种方法将类的声明(包含成员变量和成员函数原型)放在头文件中,而将成员函数的具体实现放在源文件中。这样做的好处包括提高代码的可维护性和编译效率。

  • 头文件(Box.h)源文件(Box.cpp) 示例:
// Box.h
#ifndef BOX_H
#define BOX_Hclass Box {
public:double length;double width;double height;double getVolume(); // 成员函数声明
};#endif// Box.cpp
#include "Box.h"double Box::getVolume() {return length * width * height; // 成员函数定义
}

在头文件Box.h中,我们声明了Box类和getVolume函数的原型。在源文件Box.cpp中,我们定义了getVolume函数的具体实现。

3.3如何选择

  • 简单类或模板类:倾向于使用声明与定义不分离的方法,因为这简化了代码结构,减少了文件数量。
  • 复杂类或大型项目:推荐声明与定义分离的方法。这种方式不仅能提高编译效率(只有在类实现改变时才需要重新编译源文件),还有助于隐藏实现细节,提升代码的模块化和可维护性。

4.类的访问限定符与封装

在C++中,类的封装是通过访问限定符来实现的,它们定义了类成员的访问范围和权限。封装不仅能保护对象的状态不被外部随意访问,还能通过定义良好的接口与外界交互,是面向对象编程中的一个核心概念。

4.1访问限定符

C++中主要有三种访问限定符:publicprivateprotected,它们各自的含义如下:

  • public:公有成员在任何地方都能被访问。
  • private:私有成员只能被其所在类的成员函数访问。
  • protected:受保护成员可以被其所在类以及所有子类的成员函数访问。

使用这些访问限定符可以精确控制类成员的访问权限,防止外部代码直接访问内部状态或执行不应该被外部调用的操作。

class Box {
private:double width;  // 宽度,私有成员public:double length; // 长度,公有成员void setWidth(double wid); // 公有成员函数double getWidth(void);     // 公有成员函数
};void Box::setWidth(double wid) {width = wid;  // 私有成员,只能在类内部访问
}double Box::getWidth(void) {return width; // 私有成员,只能在类内部访问
}

在这个例子中,width是一个私有成员,它只能通过类的公有成员函数setWidthgetWidth来访问和修改。这就是封装的体现:通过公有接口暴露必要的操作,而将实现细节隐藏起来。

4.2封装

封装是面向对象编程中用于限制对对象成员的直接访问的一种机制。它有以下几个重要作用:

  • 保护数据:通过将数据成员设置为私有,可以防止外部代码直接修改对象的内部状态,从而避免数据的不一致或损坏。
  • 简化接口:通过公有成员函数提供操作数据的方法,可以简化对象的使用,使外部代码不需要了解对象内部的复杂逻辑就能使用该对象。
  • 增强可维护性:封装使得对象的内部实现可以独立于外部代码变化,只要公有接口保持不变,就可以自由改变内部实现而不影响使用该对象的代码。

5.类的作用域

在C++中,类的作用域是一个重要概念,它定义了名称(比如变量名、函数名)的可见性和生命周期。理解类的作用域对于正确地编写和维护C++程序至关重要。

基本规则

  • 类内作用域:定义在类内部的成员(包括数据成员和成员函数)在整个类内部都是可见的。这意味着类的任何成员函数都可以访问该类的所有成员,无论这些成员定义在函数之前还是之后。
  • 类外作用域:类的成员在类外默认是不可见的,除非这些成员被声明为public。访问控制符(publicprivateprotected)决定了类成员在类外的可见性。

示例代码

#include <iostream>class MyClass {
private:int a = 1;  // 私有成员变量,只能在类内部访问public:int b = 2;  // 公有成员变量,可以在类外部访问void display() {std::cout << "私有成员a的值: " << a << std::endl;  // 类内部访问私有成员std::cout << "公有成员b的值: " << b << std::endl;  // 类内部访问公有成员}
};int main() {MyClass obj;// std::cout << obj.a << std::endl; // 错误:'a'是私有的std::cout << "通过类外访问公有成员b的值: " << obj.b << std::endl;  // 类外部访问公有成员obj.display();  // 调用公有成员函数,它可以访问私有和公有成员return 0;
}

类的作用域不仅定义了成员的可见性和访问权限,还影响着代码的组织和结构。合理利用类的作用域可以提高代码的可读性和维护性,避免命名冲突,并保护数据不被非法访问。

6.类的实例化

在C++中,类实例化是指根据类模板创建对象的过程。类本身像是一个蓝图,描述了对象的结构和行为,但直到我们创建了类的实例,即对象,这些描述才具有实际意义。

6.1概念

当我们实例化一个类时,实际上是在内存中分配了一块区域来存储该类的数据成员,并根据类定义初始化这些数据。这个过程可以通过调用类的构造函数来完成,构造函数是一种特殊的成员函数,专门用于初始化新创建的对象。

6.2实例化方式

C++提供了多种实例化类的方式,但最基本的两种是:

  1. 在栈上实例化:这是最简单的创建对象的方式,类似于基本数据类型的声明。例如,如果有一个MyClass类,我们可以简单地通过MyClass obj;来在栈上创建一个MyClass类型的对象obj。这种方式创建的对象会在离开其作用域时自动被销毁。

  2. 在堆上实例化:通过使用new操作符,在堆上动态分配内存来创建对象。例如,MyClass* obj = new MyClass();创建了一个指向MyClass类型的新对象的指针obj。使用这种方式创建的对象不会自动销毁,需要手动使用delete操作符来释放内存。

简单示例代码

class MyClass {
public:MyClass() {} // 构造函数
};int main() {MyClass obj; // 在栈上实例化对象MyClass* pObj = new MyClass(); // 在堆上实例化对象delete pObj; // 释放堆上对象的内存
}

7.类成员的储存

7.1计算类对象的大小

类对象的大小是其所有非静态成员的大小总和,但这个计算受内存对齐的规则影响。静态成员不占用类对象的存储空间,因为静态成员是被类的所有实例共享的。

示例代码:

#include <iostream>class MyClass {
public:char a;    // 1 byteint b;     // 4 bytesdouble c;  // 8 bytes
};int main() {std::cout << "Size of MyClass: " << sizeof(MyClass) << " bytes" << std::endl;return 0;
}

 

这个示例中,尽管char, int, double分别占1, 4, 8字节,类的总大小可能大于13字节,这取决于编译器如何对成员bc进行内存对齐。 

7.2类对象的储存方式

类对象可以存储在堆或栈上。选择哪种方式取决于对象的预期使用寿命和程序设计。

  • 栈上存储:创建时简单,由编译器自动管理内存。对象在其声明的作用域结束时自动销毁。
  • 堆上存储:使用new关键字在堆上分配内存,适用于生命周期长或大小可变的对象。需要程序员手动管理内存,使用delete释放。

7.2.1成员变量的储存

  • 非静态成员变量:这些变量的存储空间直接包含在每个类对象中。也就是说,每当创建一个类的实例时,每个非静态成员变量都会在内存中占有一份独立的空间。这些成员的排列和大小可能受到内存对齐的影响,导致类的实际占用空间可能大于各成员大小的简单累加。

  • 静态成员变量:静态成员变量不属于类的某个特定实例,而是由类的所有实例共享。它们的存储在所有对象之外,通常在程序的全局数据区或静态存储区。静态成员变量只有一份副本,无论创建多少个类实例。

7.2.2成员函数的储存

  • 非静态成员函数:与静态成员变量不同,非静态成员函数并不存储在每个对象中。相反,所有对象共享同一段成员函数代码,而不是在每个对象中复制一份函数代码。这意味着成员函数不会增加单个对象的大小。

  • 静态成员函数:与非静态成员函数类似,静态成员函数也不存储在对象中。它们属于类本身,而非类的某个实例,并且可以在没有创建类实例的情况下被调用。静态成员函数同样不增加对象的大小。

  • 虚函数:当类中包含虚函数时,C++实现通常会在每个对象中添加一个指向虚函数表(vtable)的指针。虚函数表是一个包含指向类虚函数的指针的数组。这意味着含有虚函数的类的对象会比没有虚函数的类的对象大一个指针的大小。

class MyClass {
public:int data;              // 非静态成员变量static int count;      // 静态成员变量void display() const { // 非静态成员函数std::cout << data;}static void showCount() { // 静态成员函数std::cout << count;}
};int MyClass::count = 0; // 静态成员变量的初始化int main() {MyClass obj;std::cout << "Size of object: " << sizeof(obj) << " bytes" << std::endl; // 显示对象大小MyClass::showCount(); // 调用静态成员函数obj.display(); // 调用非静态成员函数return 0;
}

 

在这个示例中,data是每个对象中实际占用空间的非静态成员变量,而成员函数(无论是静态的还是非静态的)不占用对象的存储空间。静态成员变量count存储在所有对象之外,并由所有对象共享。

7.3类/结构体内存对齐

内存对齐是优化数据存取效率的关键编程实践,特别是在处理结构体和类时。这涉及如何在内存中布局类或结构体的成员,以便符合处理器访问内存的最优方式。

7.3.1内存对齐的基本规则

  1. 对齐需求:一个类型的对齐需求通常由该类型的大小决定。例如,类型大小为4字节的int通常需要按4字节对齐。这意味着其地址必须是4的倍数。

  2. 结构体/类的对齐:一个结构体或类的总对齐需求通常由其最大成员的对齐需求决定。结构体或类的实际对齐方式会影响其总大小,因为可能在成员之间或末尾添加填充字节来满足对齐需求。

  3. 填充:为满足对齐需求,编译器可能在成员之间插入填充字节。填充确保每个成员都在其对齐需求指定的地址边界上开始。

示例:内存对齐的影响

考虑以下结构体示例,展示了如何计算大小并理解可能的内存填充。

#include <iostream>struct Sample {char a;    // 1字节int b;     // 4字节,通常要求4字节对齐char c;    // 1字节
};int main() {std::cout << "Size of Sample: " << sizeof(Sample) << " bytes" << std::endl;return 0;
}

 

在这个结构体中,尽管charint成员的总大小是6字节(1 + 4 + 1),最终的结构体大小是12字节,具体取决于编译器和平台的内存对齐策略。这是因为:

  • b 要求4字节对齐,因此在a后可能需要插入3字节的填充以确保b从4字节边界开始。
  • c后可能需要额外填充以保证整个结构体的大小为最大对齐要求的倍数(在这里是4字节)。

控制内存对齐

在C++中,可以使用特定的编译器指令或属性来控制内存对齐。例如,GCC和Clang支持__attribute__((aligned(x))),而MSVC支持__declspec(align(x)),用来指定变量或结构体成员的最小对齐。

struct __attribute__((aligned(8))) AlignedSample {char a;int b;char c;
};

在这个例子中,AlignedSample的每个实例都将按照至少8字节的边界对齐。这样的手动对齐可以帮助提高内存访问效率,尤其是在频繁访问数据时,但也可能导致内存使用效率降低。

8.this指针

在C++中,this指针是一个特殊的指针,它在每个非静态成员函数中隐含地存在。这个指针指向调用该成员函数的对象的地址。理解this指针的作用和特性对于编写面向对象的C++代码非常重要。

8.1概述

this指针是每个类的非静态成员函数的隐含参数,由编译器自动提供。它用于指向调用成员函数的对象。由于每个对象的非静态成员函数访问的是相同的代码,this指针提供了一种方法来解析对象特定的数据。

8.2为什么引入this指针

this指针的引入主要是为了解决以下几个问题:

  1. 区分同名成员和局部变量:在成员函数内部,可能会有与类的成员变量同名的局部变量。this指针可以用来区分这些变量。通过this->成员名,可以明确指出访问的是成员变量而非局部变量。

  2. 实现链式调用:通过在成员函数中返回*this,可以实现对同一个对象的连续操作。这样的方法常用于设计流畅接口(Fluent Interface)和方法链。

  3. 返回对象自身的引用:在某些需要返回调用对象自身的成员函数中,this指针使得函数能返回当前对象的引用。

8.3this指针的特性

this指针具有以下特性:

  1. 只能在类的非静态成员函数中使用:静态成员函数不与特定的对象关联,因此不能使用this指针。

  2. 是一个常量指针this指针本身不能被修改。它始终指向调用对象。

  3. 类型:在一个类T的成员函数中,this指针的类型是T* const,即一个指向T类型的常量指针。这意味着你不能改变this指针的指向(即this本身是常量),但可以修改this指向的对象的成员。

  4. 本质上是“成员函数”的形参:this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。

  5. 不需要用户传递:this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。

class MyClass {
public:int value;// 使用this指针区分成员变量和参数void setValue(int value) {this->value = value; // 明确指定访问成员变量value}// 返回对象自身的引用实现链式调用MyClass& setValueAndReturnSelf(int value) {this->value = value;return *this;}
};int main() {MyClass obj;obj.setValue(5);obj.setValueAndReturnSelf(10).setValue(15); // 链式调用示例
}

9.小结

在本博客中,我们深入探讨了C++中类和对象的基本概念。从面向对象的引入、类的定义、访问限定符和封装,到类的实例化、成员存储、内存对齐以及this指针的作用和特性,每一部分都是理解和运用C++面向对象编程的关键。这些基础知识不仅帮助我们更好地组织代码,提高程序的可读性和维护性,还是构建复杂系统时不可或缺的工具。C++ 类和对象(二),不见不散!

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

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

相关文章

Blast生态借贷协议Pac Finance陷“清算”风波,兄弟项目ParaSpace曾上演内斗

Blast生态协议又出事了。4月11日晚间&#xff0c;有用户发现借贷协议Pac Finance上出现了大量ezETH清算&#xff0c;涉及金额达2400 万美元。官方回应称&#xff0c;系一位智能合约工程师的操作导致Pac Finance发行清算阈值在没有事先通知团队的情况下被意外更改。 目前社区内…

【MATLAB源码-第8期】基于matlab的DPSK的误码率仿真,差分编码使用汉明码(hanming)。

1、算法描述 差分相移键控常称为二相相对调相&#xff0c;记作2DPSK。它不是利用载波相位的绝对数值传送数字信息&#xff0c;而是用前后码元的相对载波相位值传送数字信息。所谓相对载波相位是指本码元初相与前一码元初相之差。差分相移键控信号的波形如概述图所示。 假设相对…

元宇宙漫谈|下一代社交平台是什么样子?

社交是人类历史上极为关键的社会活动&#xff0c;它必不可缺&#xff0c;方式也在不断变化。互联网和通信技术的盛行&#xff0c;带来的是以信息、电话、视频等交流模式的迭代。随即&#xff0c;社交媒体也开始蓬勃发展&#xff0c;成为主要承载大众注意力价值的载体&#xff0…

C++类引用的好处

简化代码&#xff1a;引用可以简化代码&#xff0c;使其更加易读和易懂。通过使用引用&#xff0c;可以避免在函数参数中复制大型对象&#xff0c;从而提高代码的效率和性能。 传递大型对象的效率高&#xff1a;使用引用作为函数参数传递大型对象时&#xff0c;不需要进行对象…

成都百洲文化传媒有限公司电商领域的新锐力量

在电商服务领域&#xff0c;成都百洲文化传媒有限公司凭借其专业的服务理念和创新的策略&#xff0c;正逐渐成为行业内的翘楚。这家公司不仅拥有资深的电商团队&#xff0c;还以其精准的市场定位和高效的服务模式&#xff0c;赢得了众多客户的信赖和好评。 一、专业团队&#…

UDP网络程序

上一章中&#xff0c;我们介绍了socket&#xff0c;以及TCP/UDP协议。这一章带大家实现几个UDP协议的网络服务。我们需要一个 服务端和一个客户端。 1.服务端实现 1.1socket函数 #include <sys/types.h> #include <sys/socket.h>int socket(int domain, in…

Sora视频生成模型:开启视频创作新纪元

随着人工智能技术的飞速发展&#xff0c;视频生成领域也迎来了前所未有的变革。Sora视频生成模型作为这一领域的佼佼者&#xff0c;凭借其卓越的性能和创新的应用场景&#xff0c;受到了广泛的关注与好评。本文将对Sora视频生成模型进行详细介绍&#xff0c;带您领略其魅力所在…

Linux——十个槽位,RWX

Linux——RWX 十个槽位 - 表示文件 d 表示文件夹 l 表示软链接 r权&#xff0c;针对文件可以查看文件内容 针对文件夹&#xff0c;可以查看文件夹内容&#xff0c;如ls命令 w权&#xff0c;针对表示可以修改此文件 针对文件夹&#xff0c;可以在文件夹内&#…

Qt案例 通过调用Setupapi.h库实现对设备管理器中设备默认驱动的备份

参考腾讯电脑管家-软件市场中的驱动备份专家写的一个驱动备份软件案例&#xff0c;学习Setupapi.h库中的函数使用.通过Setupapi.h库读取设备管理器中安装的设备获取安装的驱动列表&#xff0c;通过bit7z库备份驱动目录下的所有文件. 目录导读 实现效果相关内容示例获取SP_DRVIN…

Scikit-learn 快速入门篇

Sklearn 简介 scikit-learn (sklearn) 是 Python 中用于机器学习的最流行的库之一。它提供了一系列有效的算法和工具&#xff0c;涵盖各种机器学习任务&#xff0c;包括&#xff1a; 分类回归聚类降维模型选择数据预处理 Sklearn 六大模块 分类&#xff1a;预测离散类别 算…

.net6(数据库优先)命令生成上下文类和对应数据库实体

前提安装四个NuGet包 Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore.Tools Microsoft.EntityFrameworkCore.Design Microsoft.EntityFrameworkCore.SqlServer 程序包管理控制台输入命令即可生成 Scaffold-DbContext"server.;database数据库名字,trusted…

Oralce TIMESTAMP 类型转换为 JSON 失败 | oracle.sql.TIMESTAMP 问题

问题场景 使用 springboot 做的某业务查询&#xff0c;使用的数据库是 Oracle 数据库&#xff0c;数据库中的字段 TRANS_TIME 使用的数据库字段类型是 TIMESTAMP。程序中在 MyBatis 的 XML 中编写了常规的 select 查询&#xff0c;<select id"queryData" resultT…

分布式强化学习

标题 易混淆概念联邦学习与强化学习1&#xff09;联邦学习应用于强化学习2&#xff09;强化学习应用于联邦学习 时空图卷积网络&#xff08;ST-GCN&#xff09;基本概念结合训练 易混淆概念 DistributionalRL是分布RL&#xff0c;不是分布式RL。分布RL是把Q值从一个期望构建成…

2024-4-10 群讨论:JFR 热点方法采样实现原理

以下来自本人拉的一个关于 Java 技术的讨论群。关注公众号&#xff1a;hashcon&#xff0c;私信拉你 什么是 JFR 热点方法采样&#xff0c;效果是什么样子&#xff1f; 其实对应的就是 jdk.ExecutionSample 和 jdk.NativeMethodSample 事件 这两个事件是用来采样的&#xff0c…

睿尔曼复合机器人之底盘操作流程

以操作流程为例&#xff0c;介绍底盘的操作流程。 开机&#xff1a;长按电源按钮&#xff0c;蜂鸣器短响两声&#xff0c;当第三声变长鸣后松开&#xff0c;等待机器开机。 使用&#xff1a; 建立通讯&#xff1a;主要采用无线WiFi与底盘进行通讯连接 无线连接方式&#xff…

副业天花板流量卡推广,小白也可轻松操作

在如今的互联网时代&#xff0c;手机已经不仅仅是一款工具&#xff0c;更像是我们生活中的一部分&#xff0c;那么手机卡也是必需品&#xff0c;但存在的问题就是:很多手机卡的月租很贵&#xff0c;流量也不够用。所以大家都在寻找一个月租低&#xff0c;流量多的卡&#xff0c…

【AcWing】蓝桥杯集训33考前重点|基础算法|图论|数论|DP|DFS等

二分、前缀和、差分、双指针 并查集、哈希表 DFS、BFS、深度优先遍历、宽度优先遍历 最短路(SPFA、Dijikstra、Floyd)、最小生成树(kruskal) 质数、约数、最大公约数、快速幂、组合数、矩阵乘法快速幂 DP、背包问题、序列模型、区间DP、状态压缩DP 贪心 LCA树状差分 日期问题、…

计算机网络—HTTPS协议详解:工作原理、安全性及应用实践

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;ヒューマノイド—ずっと真夜中でいいのに。 1:03━━━━━━️&#x1f49f;──────── 5:06 &#x1f504; ◀️ ⏸…

2024年最佳WordPress插件

我喜欢的最佳WordPress插件&#xff08;也是经验丰富的WordPress开发者强烈推荐的&#xff09;。所有这些插件都是编码干净、超快且一流的。我还包括了对我不喜欢的插件的想法……只为了让你有进一步的了解。 目录 隐藏 1 古腾堡块&#xff1a; 2 内容&#xff1a; 3 缓存…

NC251500 coin

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目背景 假如我那时握住的不是硬币&#xff0c;而是 ... 题意简述 Rikka 和 Yuuta 在玩游戏&#xff0c;每一次他们会抛一枚硬币&#xff0c;正面向上的概率是 p&#xff0c;反面向上的概率是…