当前位置: 首页 > news >正文

04-c++类和对象(下)

一、友元

前面学习的类中,只能通过该类的公共方法访问私有数据。而如果将某个函数设置为类的友元,那么这个函数就可以直接访问该类的私有数据,破坏了类的封装性,只在某些特定的情况下使用。

友元的分类:普通全局函数作为友元、类的某个成员函数作为友元、整个类作为友元。关键字:friend。

1.全局函数作为类的友元

  • 代码演示
class Object
{friend void useObject(Object &ob);
private:char cup[32];
public:char pen[32];Object(){}Object(char *cup, char *pen){strcpy(this->cup, cup);strcpy(this->pen, pen);}
};// 定义一个全局函数
void useObject(Object &ob)
{cout << "小明正在使用" << ob.pen << endl;cout << "小明正在使用" << ob.cup << endl;
}void test27()
{Object xh_obj("小红的水杯", "小红的钢笔");useObject(xh_obj);
}
  • 运行结果
小明正在使用小红的钢笔
小明正在使用小红的水杯
  • 说明:未设置友元的时候,全局函数直接访问对象的私有数据会报错,但是设置了友元就可以访问了。将全局函数设置友元,只需要在类的首行加上函数的声明,并在前面加上 friend 关键字即可。

2.类的成员函数作为另外一个类的友元

  • 代码演示
// 向前声明Object类
class Object;
// 要将Person类中的成员函数设置为Object的友元,先定义Person类
class Person
{
private:char name[32];
public:Person(){}Person(char *name){strcpy(this->name, name);}void useCup(Object &obj);void usePen(Object &obj);
};class Object
{friend void Person::useCup(Object &obj);
private:char cup[32];
public:char pen[32];Object(){}Object(char *cup, char *pen){strcpy(this->cup, cup);strcpy(this->pen, pen);}
};// 将Person的函数在两个类的下方首先,否则没法识别到Object的数据
void Person::useCup(Object &obj) {cout << name << "正在使用" << obj.cup << endl;
}void Person::usePen(Object &obj) {cout << name << "正在使用" << obj.pen << endl;
}void test27()
{Object xh_obj("小红的水杯", "小红的钢笔");Person xm("小明");xm.usePen(xh_obj);xm.useCup(xh_obj);
}
  • 运行结果
小明正在使用小红的钢笔
小明正在使用小红的水杯
  • 说明:假设将 A 类中的成员函数设置为 B 类的友元,其步骤如下:
  1. 先定义 A 类,并且 A 类的成员函数在类外(A 和 B 类的下方)实现;
  2. 向前声明 B 类,在 A 类前面声明 B 类;
  3. 在 B 类中使用 friend 声明 A 的成员函数为友元。

3.一个类作为另外一个类的友元

  • 代码演示
// 其它代码和上面类的成员函数作为另外一个类的友元一样
// 只是不是将单个函数作为友元,而是整个类,只修改一句代码
// 将class Object中的
friend void Person::useCup(Object &obj); // 改为
friend Person;
// 这样,如果Person类中有多个成员函数需要设置为Object的友元
// 不需要一个个函数去 friend ,只需要把整个类 friend 就行
  • 总结
    1. 友元关系不能被继承,继承后面学。即:类A 是父类,类B 是 类A 的朋友,类C 是 类A 的子类,但 类B 不一定是 类C 的朋友;
    2. 友元关系是单向的。即:类 A 是类 B 的朋 友,但类 B 不一定是类 A 的朋友;
    3. 友元关系不具有传递性。即:类 B 是类 A 的朋 友,类 C 是类 B 的朋友,但类 C 不一定是类 A 的朋友。

二、数组类

数组类,本质上是一个类,可以通过这个类创建一个个数组对象,实现数组的部分功能。

  • 代码演示
class Array
{
private:// 数组的实际元素个数(数组大小)int size;// 数组可容纳的元素个数(数组容量)int capacity;// 数组首元素地址int *array;
public://  构造函数Array();Array(int capacity);Array(const Array &obj);// 析构函数~Array();// 数组的功能函数// 返回数组大小和数组容量int getSize();int getCapacity();// 尾部插入数据void pushBack(int num);// 删除尾部数据void popBack();// 遍历数组void printArray();
};Array::Array() {size = 0;// 将容量默认初始化为5capacity = 5;// 为数组申请堆区空间array = new int[capacity];
}Array::Array(int capacity) {size = 0;this->capacity = capacity;// 为数组申请堆区空间array = new int[capacity];
}Array::Array(const Array &obj) {size = obj.size;capacity = obj.capacity;// 为数组申请堆区空间array = new int[capacity];// 将旧对象的数据通过内存拷贝拷贝给新对象memcpy(array, obj.array, sizeof(int) * capacity);
}Array::~Array() {// 释放前先判断数组是否为空if(array != NULL){// 注意释放的是数组,加 []delete [] array;array = NULL;}
}int Array::getSize() {return size;
}int Array::getCapacity() {return capacity;
}void Array::pushBack(int num) {// 插入前先判断数组是否已满if (size == capacity){// 如果满了就为数组增加一倍的空间int *tempArray = new int[capacity * 2];// 将以前的数组数据拷贝给新开辟的数组空间memcpy(tempArray, array, sizeof(int) * capacity);capacity = capacity * 2;// 释放以前的数组delete [] array;// 指向新开辟的空间array = tempArray;}// 末尾插入数据array[size] = num;size++;
}void Array::popBack() {// 先判断数组是否为空if (NULL == array){cout << "数组为空" << endl;return;}size--;
}void Array::printArray() {int i = 0;for (i = 0; i < size; i++){cout << array[i] << " ";}cout << endl;
}void test28()
{// 创建一个数组对象Array array1;// 给数组添加5个元素array1.pushBack(11);array1.pushBack(22);array1.pushBack(33);array1.pushBack(44);array1.pushBack(55);// 打印数组大小容量cout << "size = " << array1.getSize() << " capacity = " << array1.getCapacity() << endl;// 遍历数组array1.printArray();// 添加一个元素,打印大小和容量array1.pushBack(66);cout << "size = " << array1.getSize() << " capacity = " << array1.getCapacity() << endl;array1.printArray();// 删除一个,打印信息array1.popBack();cout << "size = " << array1.getSize() << " capacity = " << array1.getCapacity() << endl;array1.printArray();
}
  • 运行结果
size = 5 capacity = 5 
11 22 33 44 55        
size = 6 capacity = 10
11 22 33 44 55 66     
size = 5 capacity = 10
11 22 33 44 55 
  • 注意:
    1. 数组类中包含数组的必要数据:数组的的大小,即实际的元素个数,数组的容量,数组首元素的地址;
    2. 数组初始化,除了初始化容量以外,还得申请相应大小的堆区空间;
    3. 插入数据的时候,如果数组的大小和容量相等,代表数组已满,要插入需要先追加空间。但追加空间不是在原空间后面追加,而是新申请内存(为原来的内存加新申请的空间的大小总和),然后再将原来空间的数据,拷贝到新空间。不在后面直接追加的原因是,不确定原空间后面的空间是否存储了其它数据,后面添加可能占用非法内存。

三、运算符重载

运算符重载:就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型的运算需求。

关键字:operator 比如重载 + 运算符,其函数名 operator+

一元运算符:运算符需要的运算对象是一个,如i++ --i等;二元运算符:运算符需要的运算对象是两个,如+ - *等。

1.重载运算符的步骤

  1. 首先必须明确:运算符左边的运算符对象是自定义对象还是其他;
  2. 如果左边是其他,必须使用全局函数完成运算符重载,且全局函数必须是友元;
  3. 如果左边是自定义对象,可以使用成员函数或全局函数完成运算符重载,推荐用成员函数实现。如果使用成员函数,可以少一个参数,如果使用全局函数,不可以少参数,且必须把全局函数设置友元。

先大致了解重载运算符的步骤及注意事项,结合下面的案例具体学习。

2.运算符重载应用

2.1全局函数重载 << 运算符

  • 代码演示
// 定义一个 Person 类
class Person
{friend void operator<<(ostream &out, Person &obj);
private:int num;// string 需要包含 <string> 头文件string name;float score;
public:Person(){num = 000;name = "admin";score = 0.0f;}Person(int num, string name, float score){this->num = num;// string 中重载了 = 运算符,因此这里可以直接赋值this->name = name;this->score = score;}void showPerson(){cout << "num = " << num << " name = " << name << " score = " << score << endl;}
};// 重载 << 运算符
void operator<<(ostream &out, Person &obj)
{out << "num = " << obj.num << " name = " << obj.name << " score = " << obj.score << endl;
}void test29()
{// 创建一个对象并初始化Person xm(101, "小明", 88.5);xm.showPerson();// 之前我们想要查看对象信息,需要通过公共方法来访问// 现在可以通过 cout << 对象 直接访问cout << xm;Person xh(102, "小红", 85.0);cout << xh;
}
  • 运行结果
num = 101 name = 小明 score = 88.5
num = 101 name = 小明 score = 88.5
num = 102 name = 小红 score = 85
  • 说明:

    1. 上面重载了 << 运算符,首先 << 左边是一个非自定义对象,因此需要通过全局函数完成运算符重载;
    2. 因为这里是需要通过重载函数操作对象数据的,因此需要将重载函数设置为类的友元;
    3. 这里重载 << 运算符只是针对当前类创建的对象有效;
    4. operator<<为重载函数名,<< 左边的作为函数的第一个参数,右边的作为函数的第二个参数;
    5. cout << xm是编译器优化后的函数调用方式,其本质是operator<<(cout, xm)
  • 还可以完成链式操作,连续输出多个对象:

// 还是上面案例的代码
// 修改函数
ostream& operator<<(ostream &out, Person &obj)
{out << "num = " << obj.num << " name = " << obj.name << " score = " << obj.score << endl;return out;
}
// 函数修改了,记得修改类的友元
friend ostream&  operator<<(ostream &out, Person &obj);
// 在 test29 函数中添加
cout << xh << xm;
  • 运行结果
num = 102 name = 小红 score = 85  
num = 101 name = 小明 score = 88.5
  • 说明:
    1. 上面的链式操作可以一次输出多个对象的信息;
    2. 原理是将 out 返回,即 cout 的引用,那么上一次函数运算的结果 cout 继续作为 << 的左值,完成连续输出,实现链式操作。

2.2全局函数重载 >> 运算符

这里要实现通过cin >> 对象给对象成员赋值

  • 代码演示
// 还是上面的类
// 重载 >> 运算符
istream &operator>>(istream &in, Person &obj) {in >> obj.num >> obj.name >> obj.score;return in;
}
// 将全局函数设置为类的友元
friend istream &operator>>(istream &in, Person &obj);// 调用函数运行
void test30() {Person jack;cin >> jack;cout << jack;
}
  • 运行结果
101 jack 88
num = 101 name = jack score = 88
  • 和上面重载 >> 运算符原理类似,不做过多解释。

2.3全局函数重载 + 运算符

这里要实现两个对象的加法,即:对象1 + 对象2

  • 代码演示
// 还是使用上面的 Person 类
// 重载 + 运算符
Person operator+(Person obj1, Person obj2)
{// 定义一个临时对象用于存放运算结果Person temp;temp.num = obj1.num + obj2.num;temp.name = obj1.name + obj2.name;temp.score = obj1.score + obj2.score;return temp;
}
// 添加友元
friend Person operator+(Person obj1, Person obj2);
// 将之前的重载 << 函数的第二个参数引用传递改为值传递
ostream &operator<<(ostream &out, Person obj) // 同样友元也记得该// 调用函数执行    
void test31()
{Person jack(101, "jack", 88.5);Person rose(102, "rose", 77.5);cout << jack + rose;
}    
  • 运行结果
num = 203 name = jackrose score = 166
  • 说明:
    1. Person operator+(Person obj1, Person obj2)的返回值不能为引用,因为函数运行结束,临时变量 temp 就释放了,如果返回引用的话,后面 cout 输出会访问非法内存,因此,重载 << 运算符的第二个参数也改为值传递了,这样才能类型匹配;
    2. 如果返回值为非引用,那么它返回的就是具体的值,那么重载 + 运算符的第一个参数也要非引用,因为如果进行链式操作,那么会将上一次 + 运算的结果作为下一次 + 运算的左值,但上一次运算结果是具体值,不能对值取引用,因此第一个参数不能直接引用传递;
    3. 如果第一个参数一定要引用传递的话,那么要加 const 修饰为常引用,才能对值取引用。

2.4成员函数重载 + 运算符

上面的案例, + 的左值为自定义对象,因此可以通过成员函数实现运算符重载。

  • 代码演示
// 还是上面的 Person 类,只是在类中添加如下成员函数
// 成员函数重载 + 运算符Person operator+(Person obj){Person temp;temp.num = num + obj.num;temp.name = name +obj.name;temp.score = score + obj.score;return temp;}
// 调用函数执行
void test32()
{Person jack(101, "jack", 88.5);Person rose(102, "rose", 77.5);Person bob(102, "bob", 66.5);cout << jack + rose + bob;
}
  • 运行结果
num = 305 name = jackrosebob score = 232.5
  • 说明:成员函数实现重载,函数调用本质上是:jack.operator+(rose),只是被编译器简化为了jack + rose,因此只需要传一个参数,因为对象调用函数,函数内部会自动生成保存调用该函数的对象的 this 指针,因此函数内部可以直接使用调用该函数的对象的成员数据,可以少传一个参数。

2.5成员函数重载 == 运算符

直接通过 == 比较两个对象是否相等,即实现 对象1 == 对象2的判断。

  • 代码演示
// 还是上面的 Person 类,只是在类中添加如下成员函数
// 成员函数重载 == 运算符bool operator==(Person &obj){if ((num == obj.num) && (name == obj.name) && (score == obj.score))return true;return false;}
// 调用函数执行
void test33()
{Person jack(101, "jack", 88.5);Person rose(102, "rose", 77.5);Person jack2(101, "jack", 88.5);if (jack == jack2){cout << "相等" << endl;}else{cout << "不相等" << endl;}
}
  • 运行结果
相等

2.6重载 ++ – 运算符

++ 和 – 原理相同,这里就以重载 ++ 运算符为例。

重载 ++ 运算符,有两种情况, ++ 在前和在后,但是其函数名都是 operator++ ,而且该运算符的操作数只有一个,该怎样区分两种不同的情况呢,这里就用到了函数的重载,为区分两个函数,还用到了占位参数。

  • 因此分为两种情况, ++ 前置和 ++ 后置:
    1. 当编译器看到 ++a(前置++)时,它就调用 operator++(a), 先++ 后使用;
    2. 当编译器看到 a++(后置++)时,它就调用 operator++(a, int),先使用后++。
2.6.1重载前置 ++
  • 代码演示
// 还是上面的 Person 类,只是在类中添加如下成员函数
// 成员函数重载前置 ++Person& operator++() {num++;name = name + name;score++;return *this;}
// 调用函数执行
void test34() {Person jack(101, "jack", 88.5);Person bob;bob = ++jack;cout << jack;cout << bob;
}
  • 运行结果
num = 102 name = jackjack score = 89.5
num = 102 name = jackjack score = 89.5
  • 说明:重载前置 ++ 的时候,函数没有占位参数。
2.6.2重载后置 ++
  • 代码演示
// 还是上面的 Person 类,只是在类中添加如下成员函数
// 成员函数重载后置 ++Person operator++(int) {Person old_obj = *this;num++;name = name + name;score++;return old_obj;}
// 调用函数执行
void test35() {Person jack(101, "jack", 88.5);Person bob;bob = jack++;cout << jack;cout << bob;
}
  • 运行结果
num = 102 name = jackjack score = 89.5
num = 101 name = jack score = 88.5
  • 说明:
    1. 重载后置 ++ 的时候,函数有占位参数;
    2. 函数的返回值不能是引用,因为返回的是一个临时局部变量,保存的对象自增前的值,如果返回引用,变量在函数调用结束后就释放了,操作释放的变量会访问非法内存。

2.7重载 () 运算符

我们在前面调用函数的时候,都会在函数名后面加 () 表示调用函数,因此 () 又叫做函数调用运算符。重载函数调用运算符,实现通过对象加()完成函数调用。

  • 代码演示
class Print {
public:Print &operator()(char *str){cout << str;return *this;}
};void test36()
{Print obj1;obj1("hello");cout << endl;Print print;print("hello ")("world ")("hello ")("friend");cout << endl;Print()("hello ")("world ")("hello ")("friend");cout << endl;
}
  • 运行结果
hello                   
hello world hello friend
hello world hello friend
  • 说明:上面定义的类又叫仿函数。

相关文章:

04-c++类和对象(下)

一、友元 前面学习的类中&#xff0c;只能通过该类的公共方法访问私有数据。而如果将某个函数设置为类的友元&#xff0c;那么这个函数就可以直接访问该类的私有数据&#xff0c;破坏了类的封装性&#xff0c;只在某些特定的情况下使用。 友元的分类&#xff1a;普通全局函数…...

《解密奖励函数:引导智能体走向最优策略》

在强化学习领域&#xff0c;奖励函数是核心要素&#xff0c;它决定了智能体如何学习和决策。设计一个恰当的奖励函数&#xff0c;能让智能体在复杂环境中不断探索、优化&#xff0c;最终实现最优策略。 奖励函数的重要性 奖励函数就像是一个引导者&#xff0c;它告诉智能体什…...

AF3 AtomAttentionEncoder类的init_pair_repr方法解读

AlphaFold3 的 AtomAttentionEncoder 类中,init_pair_repr 方法方法负责为原子之间的关系计算成对表示(pair representation),这是原子转变器(atom transformer)模型的关键组成部分,直接影响对蛋白质/分子相互作用的建模。 init_pair_repr源代码: def init_pair_repr(…...

VScode 格式化代码空格记录

点击 -> “文件” -> “首选项" -> “设置” -> 按下图操作&#xff1a; 怎么格式化代码空格&#xff0c;先看下&#xff1a; 保存代码后&#xff0c;这代码自动格式化发&#xff0c;如下图&#xff1a; 你可以试试看就即可...

28.Marshal.PtrToStringAnsi C#例子

//怎么说呢&#xff0c;这个代码Marshal的英文意思有将军&#xff0c;控制等等&#xff0c; //我的理解是类似于console控制台。 //然后后面这个Ansi是一种ASCII的扩展&#xff0c;还有其他编码方式可选 就是一个把后面的指针转化为字符串的一个代码 这是用法…...

Git的使用流程(详细教程)

目录 01.Git是什么&#xff1f; 1.1 Git简介 1.2 SVN与Git的最主要的区别 1.3 GIt主要特点 02.Git是干什么的&#xff1f; 2.1.Git概念汇总 2.2 工作区/暂存区/仓库 2.3 Git使用流程 03.Git的安装配置 3.1 Git的配置文件 3.2 配置-初始化用户 3.3 Git可视化…...

第R3周:RNN-心脏病预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 文章目录 一、前言二、代码流程1、导入包&#xff0c;设置GPU2、导入数据3、数据处理4、构建RNN模型5、编译模型6、模型训练7、模型评估 电脑环境&#xff1a;…...

clickhouse Cannot execute replicated DDL query, maximum retries exceeded报错解决

报错信息 在clickhouse中执行DDL命令对表进行改动时&#xff0c;出现报错Cannot execute replicated DDL query, maximum retries exceeded 解决方案 一、官方解决方案 官方说这是一个特定版本的bug&#xff0c;但是实际我自己用的22.9.34版本&#xff0c;也存在这个问题&a…...

【时时三省】(C语言基础)常见的动态内存错误

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 对NULL指针的解引用操作 示例&#xff1a; malloc申请空间的时候它可能会失败 比如我申请一块非常大的空间 那么空间可能就会开辟失败 正常的话要写一个if&#xff08;p&#xff1d;&#x…...

【JVM】总结篇-字节码篇

字节码篇 Java虚拟机的生命周期 JVM的组成 Java虚拟机的体系结构 什么是Java虚拟机 虚拟机&#xff1a;指以软件的方式模拟具有完整硬件系统功能、运行在一个完全隔离环境中的完整计算机系统 &#xff0c;是物理机的软件实现。常用的虚拟机有VMWare&#xff0c;Visual Box&…...

二十三种设计模式-抽象工厂模式

抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;它提供了一种方式&#xff0c;用于创建一系列相关或相互依赖的对象&#xff0c;而不需要指定它们具体的类。这种模式主要用于系统需要独立于其产品的创建逻辑时&#xff0c;并且…...

【docker】Dockerfile 中使用宿主机代理的方式

在Dockerfile中配置代理主要有这几种方式&#xff0c;让我系统地整理一下&#xff1a; 构建参数方式&#xff08;BUILD ARG&#xff09; # 方式1&#xff1a;在Dockerfile顶部定义 ARG HTTP_PROXYhttp://proxy:7890 ARG HTTPS_PROXYhttp://proxy:7890# 方式2&#xff1a;在构…...

现代无线通信接收机架构:超外差、零中频与低中频的比较分析

写在前面&#xff1a;本博客是对三种接收机架构的学习笔记&#xff0c;仅供个人学习记录使用。内容主要是上网查阅的资料&#xff0c;以及个人的一些理解。如有错误的地方请指出&#xff01; 文章目录 一、通信机基本架构 1、射频发射级的基本组成及完成功能2、射频接收级的基…...

CSS 图片廊:网页设计的艺术与技巧

CSS 图片廊&#xff1a;网页设计的艺术与技巧 引言 在网页设计中&#xff0c;图片廊是一个重要的组成部分&#xff0c;它能够以视觉吸引的方式展示图片集合&#xff0c;增强用户的浏览体验。CSS&#xff08;层叠样式表&#xff09;作为网页设计的主要语言之一&#xff0c;提供…...

Gemini和ChatGPT全面对比分析,有什么区别和优势?

当 AI 聊天机器人首次出现时&#xff0c;每个人都在竞相发布自己的足够好的第一版 AI 聊天机器人&#xff0c;很容易在 Gemini 与 ChatGPT 等应用程序之间进行比较。但随着 Google 和 OpenAI 不断添加新功能、模型和访问其聊天机器人的方式&#xff0c;差异变得不那么明显。 现…...

Ansys Discovery 中的网格划分方法:探索模式

本篇博客文章将介绍 Ansys Discovery 中可用于在探索模式下进行分析的网格划分方法。我们将在下一篇博客中介绍 Refine 模式下的网格划分技术。 了解 Discovery Explore 模式下的网格划分 网格划分是将几何模型划分为小单元以模拟系统在不同条件下的行为的过程。这是通过创建…...

前 5 名 IPhone 解锁工具/软件

设备已禁用并且您无法访问它&#xff1f;如果您无法通过密码解锁&#xff0c;尝试 iPhone 解锁软件可能是最好的解决方案。 虽然市场上有很多免费或付费的 iPhone 解锁工具&#xff0c;但您可能不知道它们之间的区别以及如何选择最适合您的工具。 本文将介绍 5 款iPhone 解锁…...

富士通 自动进纸 扫描仪 scan 按钮 触发设置

附赠光盘里的驱动和软件都先装好&#xff0c;然后3步&#xff0c; 1&#xff0c;控制面板&#xff0c;对着设备右键&#xff0c;详细设置&#xff0c;触发对应&#xff0c;选择stream capture软件。&#xff08;差不多就这意思&#xff0c;懂的自然懂&#xff09; 2&#xff…...

SpringCloud系列教程:微服务的未来 (五)枚举处理器、JSON处理器、分页插件实现

在现代 Java 开发中&#xff0c;我们常常需要处理各种通用的功能和需求&#xff0c;诸如枚举的处理、JSON 数据处理&#xff0c;以及分页查询等。这些功能虽然看似简单&#xff0c;但在实际开发中往往涉及到许多细节和优化。为了提高开发效率、减少重复代码的编写&#xff0c;我…...

dos2unix: command not found

如果你在终端或命令行界面中遇到了“dos2unix: command not found”的错误&#xff0c;这意味着你的系统中没有安装dos2unix工具。dos2unix是一个用于将文本文件中的DOS/Mac格式的行结束符转换为Unix/Linux格式的行结束符的工具。 以下是一些解决方法&#xff1a; 安装dos2un…...

使用 Docker 查看 Elasticsearch 错误日志

在使用 Elasticsearch&#xff08;简称 ES&#xff09;的过程中&#xff0c;我们可能会遇到各种问题。为了快速定位和解决这些问题&#xff0c;查看错误日志是关键。本文将介绍如何使用 Docker 查看 Elasticsearch 的错误日志&#xff0c;并提供一些实用技巧。 1. 安装 Docker…...

Scala 访问修饰符

Scala 访问修饰符 在编程语言中&#xff0c;访问修饰符是一种重要的语法元素&#xff0c;它用于控制类、对象、特质、接口、方法和变量的访问级别。Scala作为一种多范式编程语言&#xff0c;也提供了丰富的访问修饰符&#xff0c;以实现封装和隐藏内部实现细节。本文将详细介绍…...

VisualRules规则引擎语法介绍

VisualRules规则引擎是一款用于处理复杂业务规则的引擎&#xff0c;广泛应用于金融、保险、医疗等领域。它通过将业务逻辑从代码中分离出来&#xff0c;以可配置的方式管理和执行规则。以下是VisualRules规则引擎的基本语法和使用方法&#xff1a; 1. 规则定义 规则通常由 条件…...

UDP_TCP

目录 1. 回顾端口号2. UDP协议2.1 理解报头2.2 UDP的特点2.3 UDP的缓冲区及注意事项 3. TCP协议3.1 报头3.2 流量控制2.3 数据发送模式3.4 捎带应答3.5 URG && 紧急指针3.6 PSH3.7 RES 1. 回顾端口号 在 TCP/IP 协议中&#xff0c;用 “源IP”&#xff0c; “源端口号”…...

web端显示spine动画

一、说明 &#xff08;1&#xff09;这边使用的spine版本是3.8.99 spine包含3个部分,可以将三个文件上传到cdn&#xff0c;三个文件放在相同的目录中 test.atlas 、 test.json 、test.png &#xff08;2&#xff09;pixi.js - v7.0.4 https://github.com/pixijs/pixijs &…...

【74HC192减法24/20/72进制】2022-5-17

缘由用74ls192设计一个72进制的减法计数器&#xff0c;需要有逻辑电路图-硬件开发-CSDN问答...

前端安全措施:接口签名、RSA加密、反调试、反反调试、CAPTCHA验证

文章目录 引言I 设置防爬虫功能使用robots.txt文件通过配置HTTP头部中的X-Robots-TagII 禁止打开开发者工具反复清空控制台无限debugger反调试检查是否按下了F12或其他调试快捷键禁用右键监听调试快捷键例子III 屏蔽粘贴/复制/剪切/选中IV 知识扩展: javascript内置命令调试分…...

算法攻略:顺序表的进阶之路——移除元素

题目如下&#xff1a; 思路&#xff1a; 双指针法 nums[src] val&#xff0c;srcnums[src] ! val&#xff0c;src的值赋值给dst&#xff0c;src和dst都 注&#xff1a; 1&#xff09;双指针法&#xff1a;只是抽象出了两个指向数组的变量&#xff0c;并不是真的指针。 2&#…...

zookeeper+kafka

一、zookeeper 1.概述 zoo: 开源的分布式框架协调服务 zookeeper的工作机制&#xff1a;基于观察者模式设计的分布式结构&#xff0c;负责存储和管理架构当中的元信息&#xff0c;架构当中的应用接受观察者的监控&#xff0c;一旦数据有变化&#xff0c;通知对应的zookeeper&a…...

大循环引起CPU负载过高

一、问题背景 环境&#xff1a;jdk1.8 tomcat7 在一次发布时&#xff0c;cpu出现负载过高&#xff0c;其负载突破200%&#xff0c;并且响应时间也大幅度超时。 二、问题分析 【1】发布前做过压测&#xff0c;并没有发现cpu异常升高的现象&#xff0c;所以其可能与生产环境的请…...

xdoj ROT13加密

标题 ROT13加密 问题描述 ROT13是一种古典加密方法&#xff0c;其加密原理是把一个字母用字母表位置相距13的字母来进行 替换&#xff0c;例如字母‘a’用字母‘n’来替换&#xff0c;字母‘z’用字母‘m’来替换。 输入一段字符串&#xff0c;然后把其中的大小写字母按照上…...

图数据库 | 17、高可用分布式设计(上)

我们在前面的文章中&#xff0c;探索了多种可能的系统扩展方式&#xff0c;以及每种扩展方式的优劣。 本篇文章将通过具体的架构设计方案来对每一种方案的设计、投入产出比、各项指标与功能&#xff0c;以及孰优孰劣等进行评价。 在设计高性能、高可用图数据库的时候&#xf…...

五类推理(逻辑推理、概率推理、图推理、基于深度学习的推理)的开源库 (一)

在开发中&#xff0c;有一些开源库可以实现不同类型的推理&#xff0c;包括逻辑推理、概率推理、图推理、基于深度学习的推理等。以下是五类推理&#xff08;逻辑推理、概率推理、图推理、基于深度学习的推理&#xff09;的现成开源库&#xff0c;它们各自的功能、特点和适用场…...

java Redisson 实现限流每秒/分钟/小时限制N个

1.引入maven包: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.redisson</groupId><artifactId>red…...

麒麟操作系统服务架构保姆级教程(八)数据库拆分静态业务拆分和负载均衡

当我们网站的访问量提升上来了&#xff0c;平均每分钟上千条访问量&#xff0c;但是服务器的性能是有限的&#xff0c;所以就需要将单台的架构进行拆分了&#xff0c;但是web服务器的内容不同怎么办&#xff0c;就会用到咱们的共享存储&#xff0c;两台web服务器今天咱们将LNMP…...

LQ24fresh

目录 C. 录入成绩 D. 标记名字 E. 奖杯排列 C. 录入成绩 &#xff08;1&#xff09;以国特 G 为切入点&#xff0c;枚举每一个 G 单独时是否为合法字符串&#xff0c;若合法 G1 有多少个 &#xff08;2&#xff09;用到的两个 string 函数&#xff1a; s.erase( i, a ) &…...

Postman[8] 断言

1.常见的断言类型 status code: code is 200 //检查返回的状态码是否为200 Response body&#xff1a; contain string //检查响应中包含指定字符串包含指定的值 response body:json value check/ /检查响应中其中json的值 Response body&#xff1a; is equal to string …...

YOLOv8/YOLOv11改进 添加CBAM、GAM、SimAM、EMA、CAA、ECA、CA等多种注意力机制

目录 前言 CBAM GAM SimAM EMA CAA ECA CA 添加方法 YAML文件添加 使用改进训练 前言 本篇文章将为大家介绍Ultralytics/YOLOv8/YOLOv11中常用注意力机制的添加&#xff0c;可以满足一些简单的涨点需求。本文仅写方法&#xff0c;原理不多讲解&#xff0c;需要可跳…...

C语言return与 ? :

上次讲解过一次函数&#xff0c;函数要配合return返回东西&#xff0c;但是在编写一些程序的时候我发现了很多冷门逻辑语法还没有掌握&#xff0c;当时讲课也是看一眼就过去了&#xff08;死去的记忆开始攻击我&#xff09; Return&#xff0c;爽&#xff01; 现在有一个小问…...

持续大额亏损,销量增幅有限,北汽蓝谷依旧黯然神伤

撰稿 | 行星 来源 | 贝多财经 “起了个大早&#xff0c;赶了个晚集”&#xff0c;用在如今的北汽蓝谷身上再合适不过。 2025年的第一个工作日&#xff0c;北汽蓝谷新能源科技股份有限公司&#xff08;SH:600733&#xff0c;简称“北汽蓝谷”&#xff09;对外披露了子公司北京…...

(五)开机自启动以及scp工具文件传输小问题

文章目录 程序开机自启动先制作一个可执行程序第一种 通过命令行实现程序开机自启动第二种 通过 Linux 系统镜像实现程序开机自启动 scp工具文件传输小问题 程序开机自启动 原因&#xff1a;做成产品后&#xff0c;用户直接开机使用&#xff0c;总不能在开机执行程序后才可以使…...

数据挖掘——支持向量机分类器

数据挖掘——支持向量机分类器 支持向量机最小间隔面推导基于软间隔的C-SVM非线性SVM与核变换常用核函数 支持向量机 根据统计学习理论&#xff0c;学习机器的实际风险由经验风险值和置信范围值两部分组成。而基于经验风险最小化准则的学习方法只强调了训练样本的经验风险最小…...

自动化办公 | 根据成绩进行自动评级

今天我们将介绍一个常见的自动化办公需求&#xff1a;根据成绩自动评级。通过这篇文章&#xff0c;我们将介绍如何利用Python进行自动化办公&#xff0c;将表格中的成绩根据预定的规则进行评级&#xff0c;并生成一个新的带评级信息的表格。 需求背景 我们有一个表格&#xf…...

Java强引用、软引用、弱引用、虚引用的区别?

大家好&#xff0c;我是锋哥。今天分享关于【Java强引用、软引用、弱引用、虚引用的区别&#xff1f;】面试题。希望对大家有帮助&#xff1b; Java强引用、软引用、弱引用、虚引用的区别&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在Java中&#…...

pikachu靶场--目录遍历和敏感信息泄露

pikachu靶场—目录遍历和敏感信息泄露 目录遍历 概述 在web功能设计中,很多时候我们会要将需要访问的文件定义成变量&#xff0c;从而让前端的功能便的更加灵活。 当用户发起一个前端的请求时&#xff0c;便会将请求的这个文件的值(比如文件名称)传递到后台&#xff0c;后台再…...

【Unity3D】UGUI Canvas画布渲染流程

参考文档&#xff1a;画布 - Unity 手册 Canvas组件&#xff1a;画布组件是进行 UI 布局和渲染的抽象空间。所有 UI 元素都必须是附加了画布组件的游戏对象的子对象。 参数&#xff1a; Render Mode 渲染模式&#xff1a;Screen Space - Overlay、Screen Spa…...

【办公类-47-02】20250103 课题资料快速打印(单个docx转PDF,多个pdf合并一个PDF 打印)

背景需求&#xff1a; 2023区级大课题《运用Python优化3-6岁幼儿学习活动材料的实践研究》需要做阶段资料 本来应该2024年6月就提交电子稿和打印稿。可是python学具的教学实验实在太多了&#xff0c;不断生成&#xff0c;我忙着做教学&#xff0c;都没有精力去整理。 2025年…...

ELK 使用教程采集系统日志 Elasticsearch、Logstash、Kibana

前言 你知道对于一个系统的上线考察&#xff0c;必备的几样东西是什么吗&#xff1f;其实这也是面试中考察求职者&#xff0c;是否真的做过系统开发和上线的必备问题。包括&#xff1a;服务治理(熔断/限流) (opens new window)、监控 (opens new window)和日志&#xff0c;如果…...

把vue项目或者vue组件发布成npm包或者打包成lib库文件本地使用

将vue项目发布成npm库文件&#xff0c;第三方通过npm依赖安装使用&#xff1b;使用最近公司接了一个项目&#xff0c;这个项目需要集成到第三方页面&#xff0c;在第三方页面点击项目名称&#xff0c;页面变成我们的项目页面&#xff1b;要求以npm库文件提供给他们&#xff1b;…...

遇到复杂的 递归查询sql 需要oracle 转pgsql 可以把数据表结构给ai

遇到复杂的 递归查询sql 需要oracle 转pgsql 可以把数据表结构给ai 并且 建立备份表 把需要的很少的数据放到表里面 这样 ai 可以很好的判断sql 咋写 还可以&#xff0c;让ai解释oracle sql 然后拿到描述和表和字段&#xff0c;给ai让他生成pgsql 的sql&#xff0c;亲测有效...