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

【C++】继承(详解)

前言:今天我们正式的步入C++进阶内容的学习了,当然了既然是进阶意味着学习难度的不断提升,各位一起努力呐。

💖 博主CSDN主页:卫卫卫的个人主页 💞
👉 专栏分类:高质量C++学习 👈
💯代码仓库:卫卫周大胖的学习日记💫
💪关注博主和博主一起学习!一起努力!
在这里插入图片描述


什么是继承

C++中的继承是一种面向对象编程的特性,它允许一个类(子类)继承另一个类(父类)的属性和方法,并且可以添加自己的属性和方法。通过继承,子类可以重用父类的代码,减少重复编写代码的工作量。在C++中,使用关键字"extends"可以声明一个类继承另一个类。子类将自动继承父类的非私有成员和方法,并可以通过重写(override)父类的方法或添加新方法来实现自己的行为。(光看文字大家肯定还是觉得晦涩难懂的,我们直接看代码)


继承的使用格式

在C++中,使用继承的格式如下:

class 子类名 : 访问权限 基类名
{// 子类的成员和函数声明
};

其中,子类名表示要定义的子类的名称,访问权限可以是public、protected或private,用于指定从基类继承成员的访问权限,基类名表示要继承的基类的名称。

例如,定义一个基类(父类)father和一个派生类(子类)son:

class father//父类
{
public:string name = "张三";int age = 20;
};class son: public father//public继承子类可以直接继承父类的公有对象
{
public :void print(){cout << name << endl << age << endl;}
};
int main()
{son s1;s1.print();return 0;
}

在上述例子中son是parent的子类,使用public权限继承了parent中name和age,然后用子类中的成员函数去调用print函数从而调用了父类中的成员。

结果如下:
在这里插入图片描述

如果还是不太能理解父类和子类的关系,看下图,通俗的理解就是儿子继承了父亲的遗产,并且儿子的财产依然存在。
在这里插入图片描述


继承后子类(派生类)的访问权限

在C++中,继承后的访问权限可以分为三种:public、protected和private。

公有继承(public inheritance):当通过公有继承派生一个子类时,基类的公有成员和保护成员在子类中仍然是公有的,可以直接访问。基类的私有成员在子类中是不可访问的。

保护继承(protected inheritance):当通过保护继承派生一个子类时,基类的公有成员和保护成员在子类中都变成了保护成员,它们通过子类只能被子类自身和子类的派生类访问,外部无法访问。基类的私有成员在子类中是不可访问的.。

私有继承(private inheritance):当通过私有继承派生一个子类时,基类的公有成员和保护成员在子类中都变成了私有成员,只能在子类内部访问,外部无法访问。基类的私有成员在子类中是不可访问的。

需要注意的是,继承的访问权限仅影响继承后的成员的访问权限,不会改变基类中成员本身的访问权限。
在这里插入图片描述

实例演示:

class Base {
public:int publicMember;
protected:int protectedMember;
private:int privateMember;
};class PublicDerived : public Base {
public:void example() {publicMember = 10; // 可以直接访问公有成员protectedMember = 20; // 可以直接访问保护成员// privateMember = 30; 无法访问私有成员}
};class ProtectedDerived : protected Base {
public:void example() {publicMember = 10; // 可以直接访问公有成员protectedMember = 20; // 可以直接访问保护成员// privateMember = 30; 无法访问私有成员}
};class PrivateDerived : private Base {
public:void example() {publicMember = 10; // 可以直接访问公有成员protectedMember = 20; // 可以直接访问保护成员// privateMember = 30; 无法访问私有成员}
};

总结:

  1. 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。
  2. 基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。
  3. 实际上面的表格我们进行一下总结会发现,基类的私有成员在子类都是不可见。基类的其他
    成员在子类的访问方式 == Min(成员在基类的访问限定符,继承方式),public > protected > private。
  4. 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
  5. 在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。
  6. 很多人分不清保护继承和私有继承,其实区别就是保护继承他的儿子的儿子也能访问他的保护成员和公有成员,私有继承就是只有他儿子能访问。

子类与父类

子类与父类的相互赋值转换

  1. 符号赋值“=”

注:这里我们先暂时知道赋值的规则就是切片赋值,就是把子类中的父类那部分,赋值过去即可。

在C++中,子类对象可以被隐式地转换为父类对象,但是父类对象不能被隐式地转换为子类对象。这是因为子类对象继承了父类对象的成员和方法,但父类对象并不包含子类特有的成员和方法。

以下是一个示例说明子类对象转换为父类对象的情况:

class Parent {
public:void print() {std::cout << "Parent class" << std::endl;std::cout << age << std::endl;}int age = 30;
};class Child : public Parent {
public:void print() {std::cout << "Child class" << std::endl;}
};int main() {Child child;child.age = 50;Parent parent = child;  // 子类对象隐式转换为父类对象parent.print();  // 调用父类的print()方法return 0;
}
  1. 引用
Child s1;//子类Parent& t1=st;//父类,通过引用对其进行赋值
  1. 指针
Child s1;//子类Parent* t1 = &st;//父类,通过指针进行赋值

总结来说,C++中可以将子类对象隐式地转换为父类对象,但是父类对象无法隐式地转换为子类对象。如果需要使用子类特有的成员和方法,需要进行类型转换.


同名成员变量

在C++中,当子类继承了父类时,如果子类中出现了与父类同名的成员变量,那么子类的同名成员变量会隐藏父类的同名成员变量。这称为"隐藏"(hiding)。

具体来说,如果子类定义了与父类同名的成员变量,那么子类中的同名成员变量会隐藏父类中的同名成员变量。这意味着当通过子类对象访问同名成员变量时,会优先访问子类中的成员变量,而无法直接访问到父类中的同名成员变量。

#include <iostream>
class Parent {
public:int num = 10;
};class Child : public Parent {
public:int num = 20;
};int main() {Child child;std::cout << "Child num: " << child.num << std::endl;   // 编译器还是就近原则,优先访问子类中的num,输出: Child num: 20std::cout << "Parent num: " << child.Parent::num << std::endl; //想要访问父类中的num,需要指定类域,输出: Parent num: 10return 0;
}

在这里插入图片描述

在上面的示例中,Parent类中定义了一个名为num的成员变量,初始值为10。Child类继承了Parent类,并定义了一个同名成员变量num,初始值为20。

在main函数中,我们创建了Child类的对象child。当我们通过子类对象child访问num时,会优先访问子类的同名成员变量,因此输出结果为20。如果我们需要访问父类中的同名成员变量,可以使用作用域解析符"::"来指定父类,如child.Parent::num


同名成员函数

在C++中,当子类继承了父类时,如果子类中出现了与父类同名的成员函数,那么子类的同名成员函数将隐藏父类的同名成员函数。

具体来说,如果子类定义了与父类同名的成员函数,那么子类中的同名成员函数将隐藏父类中的同名成员函数。这意味着当通过子类对象调用同名成员函数时,会优先调用子类中的成员函数,而无法直接调用到父类中的同名成员函数。

然而,与成员变量的隐藏不同的是,对于成员函数的隐藏,如果需要在子类中使用父类的同名成员函数,可以使用作用域解析符"::"来指定父类.

class Parent {
public:void print() {std::cout << "Parent print" << std::endl;}
};class Child : public Parent {
public:void print() {std::cout << "Child print" << std::endl;Parent::print();//可以通过指定域来调用}
};int main() {Child child;child.print();                // 输出: Child printchild.Parent::print();        // 输出: Parent printreturn 0;
}

子类中的默认成员函数

构造函数

在C++中,子类可以通过构造函数来初始化继承的父类成员。子类的构造函数可以调用父类的构造函数来初始化父类的成员变量。子类的构造函数在构造子类对象时被调用,而且会在子类构造函数的初始化列表中调用父类的构造函数.

注: 编译器会默认先调用父类的构造函数,再调用子类的构造函数.

class Parent
{
public:Parent(string name = "Dad", int age = 30):_name(name),_age(age){cout << "这是父类:" << _name << " " << age << endl;}protected:string _name;int _age;
};class Child: public Parent
{
public:Child(string son):_son(son){cout << "这是子类:" << _son << endl;}protected:string _son;
};int main()
{Child s1("son");return 0;
}

在这里插入图片描述
这里我们可以明显的知道,编译器先调用父类的默认构造,在调用子类的构造,所以一定要保证这里的父类的构造是有效的,以防止构造失效.


析构函数

在C++中,子类可以定义自己的析构函数,用来释放子类对象在内存中分配的资源。子类的析构函数与基类的析构函数类似,通过在类的声明中使用特殊的名称~类名()来定义。

子类的析构函数会自动调用基类的析构函数,以确保基类对象中分配的资源被正确释放。

注: 析构函数和构造函数相反,编译器默认先调用子类的析构函数,再调用父类的析构函数.

实例演示:

class Parent
{
public:~Parent(){cout << "这是父类的析构" << endl;}
protected:string _name;int _age;
};class Child: public Parent
{
public:~Child(){cout << "这是子类的析构" << endl;}
protected:string _son;
};int main()
{Child s1;return 0;
}

在这里插入图片描述


拷贝构造

在C++中,子类可以定义自己的拷贝构造函数,用于创建一个新的子类对象,该对象与已存在的子类对象具有相同的值。

注: 子类的拷贝构造函数会自动调用基类的拷贝构造函数,以确保基类对象的成员变量得到正确的复制.

class Parent
{
public:Parent(string name = "Dad", int age = 30):_name(name), _age(age){cout << "这是父类:" << _name << " " << age << endl;}protected:string _name;int _age;
};class Child : public Parent
{
public:Child(string son):_son(son){cout << "这是子类:" << _son << endl;}Child(Child& child):Parent(child)//通过切片的方式直接对父类进行了初始化,_son(child._son){cout << "拷贝构造:" << _name << " " << _age << " " << _son << endl;}
protected:string _son;
};int main()
{Child s1("son");Child s2(s1);return 0;
}

在这里插入图片描述


赋值运算符重载

子类的赋值运算符重载函数可以用来实现对象之间的赋值操作,包括赋值基类对象的成员变量和子类对象的成员变量。在赋值过程中,可以先调用基类的赋值运算符重载函数来赋值基类对象的成员变量,然后再进行子类对象的成员变量的赋值操作.

class Parent
{
public:Parent(string name = "Dad", int age = 30):_name(name), _age(age){cout << "这是父类:" << _name << " " << age << endl;}Parent& operator=(const Parent& s1){if (this != &s1){cout << "调用父类" << endl;_name = s1._name;_age = s1._age;}}protected:string _name;int _age;
};class Child : public Parent
{
public:Child(string son):_son(son){cout << "这是子类:" << _son << endl;}Child(Child& child):Parent(child),_son(child._son){cout << "拷贝构造:" << _name << " " << _age << " " << _son << endl;}Child& operator=(const Child& s1){if (this != &s1){Parent::operator=(s1);//调用父类的运算符重载,以免调用自身造成栈溢出_son = s1._son;}}
protected:string _son;
};int main()
{Child s1("son");Child s2(s1);return 0;
}

继承中的单继承与多继承

在C++中,单继承和多继承是两种不同的继承方式。

  1. 单继承:
    单继承指的是一个派生类只能继承自一个基类(一个孩子一个父亲)。在单继承中,一个派生类可以继承基类的所有成员(包括成员函数和成员变量),并且可以通过派生类对象访问这些成员。单继承的语法如下:

    class Base {// base class members
    };class Derived : public Base {// derived class members
    };
    

    在这个例子中,Derived类从Base类单继承,Derived类可以访问Base类中的所有公有成员。

  2. 多继承:
    多继承指的是一个派生类能够从多个基类继承。在多继承中,一个派生类可以继承多个基类的成员,这些成员可以通过派生类对象访问(一个孩子有多个父亲)。多继承的语法如下:

    class Base1 {// base class 1 members
    };class Base2 {// base class 2 members
    };class Derived : public Base1, public Base2 {// derived class members
    };
    

    在这个例子中,Derived类从Base1类和Base2类多继承,Derived类可以访问Base1Base2类中的所有公有成员。

需要注意的是,多继承在设计上可能会引入复杂性和冲突,需要谨慎使用。在多继承中,如果多个基类具有相同的成员函数或成员变量,派生类必须显式指明使用哪个基类的成员。另外,多继承还可能导致菱形继承问题,即继承图中出现多个路径指向同一个基类。为了解决这个问题,可以使用虚继承或其他技术。

总结起来,单继承和多继承是C++中的两种继承方式。单继承指的是派生类只能继承自一个基类,而多继承则允许派生类从多个基类继承。使用继承时需要考虑设计的简洁性和灵活性,以及可能引入的复杂性和冲突。


菱形继承

C++中的菱形继承(diamond inheritance)是多继承的一个特殊情况。当一个派生类通过两个不同的路径继承自同一个基类时,就会形成菱形继承结构。这种继承结构的名称源于它的图形表示类似于菱形。

考虑以下示例代码:

class A {
public:void funcA() {cout << "A::funcA()" << endl;}
};class B : public A {
public:void funcB() {cout << "B::funcB()" << endl;}
};class C : public A {
public:void funcC() {cout << "C::funcC()" << endl;}
};class D : public B, public C {
public:void funcD() {cout << "D::funcD()" << endl;}
};

在这里插入图片描述

在这个例子中,类D通过BC两个路径分别继承了类A,形成了菱形继承结构。这意味着类D会有两份来自A类的成员函数和成员变量。例如,D类实例可以调用funcA()方法两次,一次是通过B的路径,另一次是通过C的路径。

菱形继承可能导致以下问题:

  1. 虚函数二义性(Virtual Function Ambiguity):如果在菱形继承结构中,派生类中存在同名的虚函数,那么在派生类中访问这个虚函数时将产生二义性,编译器不知道应该使用哪个父类的虚函数实现。

  2. 数据冗余(Data Redundancy):由于菱形继承结构中派生类从两个不同的路径继承了同一个基类,导致派生类中会存在两份相同的成员变量。

为了解决菱形继承带来的问题,可以使用以下方法:

  1. 虚拟继承(Virtual Inheritance)是C++中一种特殊的继承方式,用于解决多继承中的菱形继承问题。通过使用虚拟继承,可以确保在派生类中只包含一个共享的基类子对象,避免了数据冗余和虚函数二义性的问题。

虚拟继承的特点有:

虚拟继承只发生在最顶层的派生类中,而不会在派生类的派生类中发生。也就是说,只有直接派生自基类的派生类才能使用虚拟继承。

虚拟继承会在内存布局中引入一个额外的指针(虚表指针)来维护虚拟继承的关系。这个指针指向了虚拟基类的子对象,用于访问虚基类的成员。

如果虚拟基类有自己的派生类,那么虚拟继承会优先选择这个派生类中的虚基类子对象作为共享对象

  1. 重写和调用具体的父类函数:通过在派生类中重写同名的虚函数,并在派生类中显式调用具体的父类函数,可以解决虚函数二义性的问题。

综上所述,菱形继承是C++多继承的一个特殊情况,可能会引发虚函数二义性和数据冗余的问题,可以通过虚继承和重写父类函数的方式来解决这些问题。


好啦,今天的内容就到这里啦,下期内容预告C++中的多态.


结语:进阶的内容有点繁杂,大家一起加油呐!。


🌏🗺️ 这里祝各位接下来的每一天好运连连 💞💞

相关文章:

【C++】继承(详解)

前言&#xff1a;今天我们正式的步入C进阶内容的学习了&#xff0c;当然了既然是进阶意味着学习难度的不断提升&#xff0c;各位一起努力呐。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f449; 专栏分类:高质量&#xff23;学习 &#x1f448; &#…...

网络io与select,poll,epoll

前言 网络 IO&#xff0c;会涉及到两个系统对象&#xff0c;一个是用户空间调用 IO 的进程或者线程&#xff0c;另一个是内核空间的内核系统&#xff0c;比如发生 IO 操作 read 时&#xff0c;它会经历两个阶段&#xff1a; 1. 等待数据准备就绪 2. 将数据从内核拷贝到进程或…...

【Linux】多线程(一万六千字)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 线程的概念 线程的理解(Linux系统为例) 在Linux系统里如何保证让正文部分的代码可以并发的去跑呢&#xff1f; 为什么要有多进程呢&#xff1f; 为…...

sh脚本笔记2

test条件测试 语法 条件测试语法说明语法1&#xff1a;test <测试表达式>这是利用test命令进行条件测试表达式的方法。test命令和“<测试表达式>”之间至少有一个空格语法2&#xff1a;[ <测试表达式> ]这是通过[]&#xff08;单中括号&#xff09;进行条件…...

js替换对象里面的对象名称

data为数组&#xff0c;val为修改前的名称&#xff0c;name为修改后的名称 JSON.parse(JSON.stringify(data).replace(/val/g, name)) &#xff1b; 1.替换data里面的对象tenantInfoRespVO名称替换成tenantInfoUpdateReqVO 2.替换语句&#xff1a; 代码可复制 let tenantInf…...

鸿蒙开发设备管理:【@ohos.settings (设置数据项名称)】

设置数据项名称 说明&#xff1a; 本模块首批接口从API version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 本模块提供设置数据项的访问功能相关接口的说明及示例。 导入模块 import settings from ohos.settings;settings.getUri…...

STM32之五:TIM定时器(2-通用定时器)

目录 通用定时器&#xff08;TIM2~5&#xff09;框图 1、 输入时钟源选择 2、 时基单元 3 、输入捕获&#xff1a;&#xff08;IC—Input Capture&#xff09; 3.1 输入捕获通道框图&#xff08;TI1为例&#xff09; 3.1.1 滤波器&#xff1a; 3.1.2 边沿检测器&#xf…...

【分布式系统】监控平台Zabbix对接grafana

以前两篇博客为基础 【分布式系统】监控平台Zabbix介绍与部署&#xff08;命令截图版&#xff09;-CSDN博客 【分布式系统】监控平台Zabbix自定义模版配置-CSDN博客 一.安装grafana并启动 添加一台服务器192.168.80.104 初始化操作 systemctl disable --now firewalld set…...

操作系统真象还原:编写硬盘驱动程序

第13章-编写硬盘驱动程序 这是一个网站有所有小节的代码实现&#xff0c;同时也包含了Bochs等文件 13.1 硬盘及分区表 13.1.1 创建从盘及获取安装的磁盘数 要实现文件系统&#xff0c;必须先有个磁盘介质&#xff0c;虽然咱们己经有个虚拟磁盘 hd60M.img&#xff0c;但它只…...

firewalld防火墙(二)

一&#xff1a;firewalld高级配置 1&#xff1a;关于iptables的知识 iptables 是Linux系统中传统的命令行防火墙管理工具&#xff0c;它基于内核的netfilter框架工作&#xff0c;用于配置和管理网络规则集&#xff0c;比如过滤&#xff08;允许/拒绝&#xff09;进出的数据包…...

Android-悬浮窗口

在Android系统中&#xff0c;如果应用需要弹出一个悬浮窗口&#xff0c;就需要申请一项特殊权限 <uses-permission android:name"android.permission.SYSTEM_ALERT_WINDOW"/>在Android O之前的系统中申请了该权限后&#xff0c;再给对应的window设置 WindowM…...

打破僵局:Foxit Reader无法打开的终极解决方案

打破僵局&#xff1a;Foxit Reader无法打开的终极解决方案 在数字化阅读时代&#xff0c;Foxit Reader作为一款广受欢迎的PDF阅读器&#xff0c;其打不开的问题无疑会给用户带来诸多不便。本文将为您提供全面的解决方案&#xff0c;从基础检查到高级技巧&#xff0c;确保您能够…...

[调试] JTAG下运行正常,从QSPI或者SD卡启动则无响应,如何查找问题

[调试] JTAG下运行正常&#xff0c;从QSPI或者SD卡启动则无响应&#xff0c;如何查找问题 一、问题现象二、用自定义fsbl替代系统默认的fsbl1. 新建fsbl_new2. 如果提示缺少xilffs库3. 使能调试信息输出 三. 启动成功和失败情况下的典型输出1. JTAG启动模式: 正常加载2. QSPI启…...

Linux内核 -- 多线程之wait_event用法

Linux Kernel 中 wait_event 的高级用法及注意事项 在Linux内核编程中&#xff0c;wait_event 系列函数是用于实现进程等待和事件通知机制的重要工具。本文将详细介绍 wait_event 的高级用法以及注意事项。 1. 基本用法 wait_event 系列宏主要包括以下几种形式&#xff1a; …...

双指针系列第 8 篇:盛水最多的容器。几句话讲明白!

Leetcode 题目链接 思路 取首尾双指针和水量如下所示&#xff0c;设高度函数为 h ( i ) h(i) h(i)&#xff0c;在下图中 h ( l ) < h ( r ) h(l) < h(r) h(l)<h(r)。 观察以 l l l 为左边界所能构成的其他水量&#xff0c;与矮的右边界搭配结果如下。 与高的…...

c++高阶-1-模板

文章目录 模板一、模板基本语法二、函数模板1.基本语法2.函数模板注意事项3.普通函数和函数模板区别4.普通函数和函数模板调用规则 三、类模板1.基本语法2.类模板和函数模板的区别3.类模板中成员函数调用时机4.类模板对象做函数参数5.类模板与继承6.成员函数的类外实现 模板 一…...

.net core 的 winform 的 浏览器控件 WebView2

在.NET Core WinForms应用程序中&#xff0c;没有直接的“浏览器控件”&#xff0c;因为WinForms不支持像WebBrowser控件那样的功能。但是&#xff0c;你可以使用WebView2控件&#xff0c;它是一个基于Chromium的浏览器内核&#xff0c;可以在WinForms应用程序中嵌入Web内容。 …...

Django QuerySet对象,all()方法

all()方法 在Django中&#xff0c;all()方法是QuerySet对象的一个方法&#xff0c;用于获取模型的所有实例。 当你调用ModelName.objects.all()时&#xff0c;Django会生成一个SQL查询&#xff0c;从数据库中获取该模型的所有记录&#xff0c;并返回一个QuerySet对象&#xf…...

自动生成网站sitemap

要在 Next.js 和 Contentlayer 项目中实现自动生成 Sitemap 的功能&#xff0c;你可以编写一个脚本&#xff0c;在每次生成文档后自动生成 Sitemap。以下是一个示例脚本&#xff0c;你可以根据自己的需求进行调整。 步骤 1&#xff1a;安装必要的依赖 首先&#xff0c;你需要…...

中国经济昆虫志(55卷)

中国经济昆虫志&#xff0c;共55卷&#xff0c;内容包括概述、形态特征、分类等。各级分类单元均编有检索表&#xff0c;每个种有特征描述、地理分布&#xff0c;有的还记载有生活习性和防治方法。为便于鉴定&#xff0c;绘制有特征图和彩色图。 包括鞘翅目天牛科、半翅目蝽科、…...

linux环境安装elasticsearch缓存数据库和Kibana客户端

linux环境安装elasticsearch缓存数据库&#xff0c;今天我们安装7.17.18版本&#xff0c;并分析遇到的问题。 一、elasticsearch安装运行 1、直接下载 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.18-linux-x86_64.tar.gz2、解压 tar -…...

OpenSSL的一些使用案例

目录 一、介绍 二、基本使用 1、Shell &#xff08;1&#xff09;文件加解密 &#xff08;2&#xff09;生成密钥文件 2、API &#xff08;1&#xff09;md5sum &#xff08;2&#xff09;AES256加解密 一、介绍 本篇博客重点不是详细描述 OpenSSL 的用法&#xff0c;只…...

常用字符串方法<python>

导言 在python中内置了许多的字符串方法&#xff0c;使用字符串方法可以方便快捷解决很多问题&#xff0c;所以本文将要介绍一些常用的字符串方法。 目录 导言 string.center(width[,fillchar]) string.capitalize() string.count(sub[,start[,end]]) string.join(iterabl…...

线程池666666

1. 作用 线程池内部维护了多个工作线程&#xff0c;每个工作线程都会去任务队列中拿取任务并执行&#xff0c;当执行完一个任务后不是马上销毁&#xff0c;而是继续保留执行其它任务。显然&#xff0c;线程池提高了多线程的复用率&#xff0c;减少了创建和销毁线程的时间。 2…...

Python28-5 k-means算法

k-means 算法介绍 k-means 算法是一种经典的聚类算法&#xff0c;其目的是将数据集分成 ( k ) 个不同的簇&#xff0c;每个簇内的数据点尽可能接近。算法的基本思想是通过反复迭代优化簇中心的位置&#xff0c;使得每个簇内的点与簇中心的距离之和最小。k-means 算法的具体步骤…...

主流国产服务器操作系统技术分析

主流国产服务器操作系统 信创 "信创"&#xff0c;即信息技术应用创新&#xff0c;作为科技自立自强的核心词汇&#xff0c;在我国信息化建设的进程中扮演着至关重要的角色。自2016年起步&#xff0c;2020年开始蓬勃兴起&#xff0c;信创的浪潮正席卷整个信息与通信技…...

【Linux】线程封装与互斥(万字)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 C多线程的用法 对原生线程进行一次封装 理解pthread线程 Linux线程互斥 进程线程间的互斥相关背景概念 互斥量mutex 操作共享变量会有问题的售票…...

5分钟教你部署MySQL8.0环境

此方法基于Windows操作系统&#xff01; 一、在MySQL官网单击downloads&#xff08;下载&#xff09;MySQLhttps://www.mysql.com/cn/ 选择在Windows操作系统下载 二、选择合适的版本 推荐下载第二种&#xff0c;安装时离线安装即可 三、安装MySQL8.0 1、找到MySQL下载完成…...

LLM应用:传统NLP任务

LLM出来以后&#xff0c;知乎上就出现了“传统NLP已死”的言论&#xff0c;但是传统NLP真的就被扔进历史的垃圾桶了吗&#xff1f; 其实&#xff0c;尽管LLM具有出色的通用能力&#xff0c;但仍然无法有效应对低资源领域的自然语言处理任务&#xff0c;如小语种翻译。为了更好地…...

基于Hadoop平台的电信客服数据的处理与分析③项目开发:搭建Kafka大数据运算环境---任务11:基础环境准备

任务描述 任务主要是安装配置基础环境&#xff0c;主要内容包括&#xff1a; 1、安装java Kafka和ZooKeeper都需要安装Java环境&#xff0c;推荐至少Java8及以上版本 2、安装ZooKeeper ZooKeeper是Kafka集群的必要组件 3、安装kafka Kafka版本包括使用的scala语言版本和kafka版…...

Golang中swtich中如何强制执行下一个代码块

switch 语句中的 case 代码块会默认带上 break&#xff0c;但可以使用 fallthrough 来强制执行下一个 case 代码块。 package mainimport ("fmt" )func main() {isSpace : func(char byte) bool {switch char {case : // 空格符会直接 break&#xff0c;返回 false…...

读书笔记-Java并发编程的艺术-第4章(Java并发编程基础)-第2节(启动和终止线程)

文章目录 4.2 启动和终止线程4.2.1 构造线程4.2.2 启动线程4.2.3 理解中断4.2.4 过期的suspend()、resume()和stop()4.2.5 安全地终止线程 4.2 启动和终止线程 在前面章节的示例中通过调用线程的start()方法进行启动&#xff0c;随着run()方法的执行完毕&#xff0c;线程也随之…...

通俗大白话理解Docker

什么是Docker Docker本质上是一种容器化技术&#xff0c;用于将应用程序及其所有依赖打包到一个标准化的单元中。这些单元&#xff08;容器&#xff09;可以在任何运行Docker的机器上运行。每个容器是相互隔离的&#xff0c;具有自己的文件系统、网络和进程空间。 以下是大白话…...

题解:CF1981C(Turtle and an Incomplete Sequence)

题解&#xff1a;CF1981C&#xff08;Turtle and an Incomplete Sequence&#xff09; Part 1&#xff1a;题意理解 地址链接&#xff1a;CF、洛谷。题面翻译&#xff1a;给定一个长度为 n n n 的序列 a a a&#xff0c;其中有一些元素未知&#xff0c;用 − 1 -1 −1 表示…...

Swift 中强大的 Key Paths(键路径)机制趣谈(上)

概览 小伙伴们可能不知道&#xff1a;在 Swift 语言中隐藏着大量看似“其貌不扬”实则却让秃头码农们“高世骇俗”&#xff0c;堪称卧虎藏龙的各种秘技。 其中&#xff0c;有一枚“不起眼”的小家伙称之为键路径&#xff08;Key Paths&#xff09;。如若将其善加利用&#xff…...

(十二)纹理和采样

纹理 在绘制三角形的过程中&#xff0c;将图片贴到三角形上进行显示的过程&#xff0c;就是纹理贴图的过程 uv坐标 如果如果图片尺寸和实际贴图尺寸不一致&#xff0c;就会导致像素不够用了的问题 纹理与采样 纹理对象(Texture)&#xff1a;在GPU端&#xff0c;用来以一…...

QT创建地理信息shp文件编辑器shp_editor

空闲之余创建一个简单的矢量shp文件编辑器&#xff0c;加深对shp文件的理解。 一、启动程序 二、打开shp文件 三、显示shp文件的几何图形 四、双击右边表格中的feature&#xff0c;主窗体显示选中feature的各个节点。 五、鼠标在主窗体中选中feature的节点&#xff0c;按鼠标左…...

解析Kotlin中扩展函数与扩展属性【笔记摘要】

1.扩展函数 1.1 作用域&#xff1a;扩展函数写的位置不同&#xff0c;作用域就也不同 扩展函数可以写成顶层函数&#xff08;Top-level Function&#xff09;&#xff0c;此时它只属于它所在的 package。这样你就能在任何类里使用它&#xff1a; package com.rengwuxianfun …...

【Java学习笔记】java图形界面编程

在前面的章节中&#xff0c;我们开发运行的应用程序都没有图形界面&#xff0c;但是很多应用软件&#xff0c;如Windows下的Office办公软件、扑克牌接龙游戏软件、企业进销存ERP系统等&#xff0c;都有很漂亮的图形界面。素以需要我们开发具有图形界面的软件。 Java图形界面编程…...

STM32入门笔记(03): ADC(SPL库函数版)(2)

A/D转换的常用技术有逐次逼近式、双积分式、并行式和跟踪比较式等。目前用的较多的是前3种。 A/D转换器的主要技术指标 转换时间 分辨率 例如&#xff0c;8位A/D转换器的数字输出量的变化范围为0&#xff5e;255&#xff0c;当输入电压的满刻度为5V时&#xff0c;数字量每变化…...

2024年7月2日 (周二) 叶子游戏新闻

老板键工具来唤去: 它可以为常用程序自定义快捷键&#xff0c;实现一键唤起、一键隐藏的 Windows 工具&#xff0c;并且支持窗口动态绑定快捷键&#xff08;无需设置自动实现&#xff09;。 卸载工具 HiBitUninstaller: Windows上的软件卸载工具 经典名作30周年新篇《恐怖惊魂夜…...

如何使用Spring Boot Profiles进行环境配置管理

如何使用Spring Boot Profiles进行环境配置管理 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨如何利用Spring Boot Profiles来管理不同环境…...

Java错题归纳(二)

1、若有如下接口A的定义&#xff0c;下列哪些类下确实现了该接口&#xff1a;C interface A { void method1(int i); void method2(int j); } A class B implements A{ void method1( ) { } void method2( ) { } } B class B implements A { void method1(int i ) { }…...

Grafana面试题精选和参考答案

目录 Grafana是什么以及它的主要应用场景 Grafana支持的数据源 Grafana的体系结构及主要组件 Grafana如何实现数据的可视化和监控 Grafana支持的图表类型 如何在Grafana中创建和编辑仪表盘 Grafana的查询编辑器功能 Grafana支持的认证方式 Grafana的性能调优建议 Gra…...

Node版本管理工具 fnm 安装使用

fnm 是一个基于 Rust 开发的 Node 版本管理工具&#xff0c;它的目标是提供一个快速、简单且可靠的方式来管理 Node.js 的不同版本。同时&#xff0c;它是跨平台的&#xff0c;支持 macOS、Linux、Windows。&#x1f680; Fast and simple Node.js version manager, built in R…...

vector模拟实现【C++】

文章目录 全部的实现代码放在了文章末尾准备工作包含头文件定义命名空间和类类的成员变量 迭代器迭代器获取函数 构造函数默认构造使用n个值构造迭代器区间构造解决迭代器区间构造和用n个值构造的冲突拷贝构造 析构函数swap【交换函数】赋值运算符重载emptysize和capacityopera…...

《每天5分钟用Flask搭建一个管理系统》第11章:测试与部署

第11章&#xff1a;测试与部署 11.1 测试的重要性 测试是确保应用质量和可靠性的关键步骤。它帮助开发者发现和修复错误&#xff0c;验证功能按预期工作。 11.2 Flask测试客户端的使用 Flask提供了一个测试客户端&#xff0c;可以在开发过程中模拟请求并测试应用的响应。 …...

Landsat数据从Collection1更改为Collection2

目录 问题解决 问题 需要注意!您使用的是废弃的陆地卫星数据集。为确保功能持续&#xff0c;请在2024年7月1日前更新。 在使用一些以前的代码时会遇到报错&#xff0c;因为代码里面用的是老的数据集 解决 对于地表反射率SR&#xff0c;需要在name中&#xff0c;将C01换为C02&…...

《每天5分钟用Flask搭建一个管理系统》第12章:安全性

第12章&#xff1a;安全性 12.1 Web应用的安全威胁 Web应用面临的安全威胁包括但不限于跨站脚本攻击&#xff08;XSS&#xff09;、SQL注入、跨站请求伪造&#xff08;CSRF&#xff09;、不安全的直接对象引用&#xff08;IDOR&#xff09;等。 12.2 Flask-Talisman扩展的使…...

Unity之创建与导出PDF

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity之创建与导出PDF TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不断探索 TechX —— 心探索、心进取&#xff01; 助力快速…...

scikit-learn超参数调优 (自动寻找模型最佳参数) 方法

网格搜索&#xff08;Grid Search&#xff09;&#xff1a; 原理&#xff1a;网格搜索通过预定义的参数组合进行穷举搜索&#xff0c;评估每一种参数组合的性能&#xff0c;选择性能最佳的参数组合。实现&#xff1a;使用GridSearchCV类。示例代码&#xff1a;from sklearn.mod…...

Qt学习:Qt窗口组件以及窗口类型

一、Qt的窗口组件有哪些 Qt是一个跨平台的C应用程序开发框架&#xff0c;它的窗口组件&#xff0c;也称为用户界面元素&#xff0c;为开发者提供了丰富的可视化界面设计选项。在Qt中&#xff0c;窗口组件主要包括&#xff1a; 窗口&#xff08;Window&#xff09;&#xff1a;…...

GoLang语言

基础 安装Go扩展 go build 在项目目录下执行go build go run 像执行脚本文件一样执行Go代码 go install go install分为两步&#xff1a; 1、 先编译得到一个可执行文件 2、将可执行文件拷贝到GOPATH/bin Go 命令 go build :编译Go程序 go build -o "xx.exe"…...

MySQL 8.0 架构 之 中继日志(Relay log)

文章目录 MySQL 8.0 架构 之 中继日志&#xff08;Relay log&#xff09;中继日志&#xff08;Relay log&#xff09;概述相关参数参考 【声明】文章仅供学习交流&#xff0c;观点代表个人&#xff0c;与任何公司无关。 来源|WaltSQL和数据库技术(ID:SQLplusDB) MySQL 8.0 OCP …...

每天一个数据分析题(三百九十九)- 逻辑回归

逻辑回归中&#xff0c;若选0.5作为阈值区分正负样本&#xff0c;其决策平面是&#xff08; &#xff09; A. wxb&#xff1d; 0 B. wxb&#xff1d; 1 C. wxb&#xff1d; -1 D. wxb&#xff1d; 2 数据分析认证考试介绍&#xff1a;点击进入 题目来源于CDA模拟题库 点…...

BASH and SH in SHELL scripts

一、执行脚本的现象 为了测试一个小的功能&#xff0c;写了一个小脚本&#xff0c;类似的内容如下&#xff1a; #!/bin/shecho "start api test ......"for((i1;i<10;i)); do echo "cur id :" $i; done echo "end."执行一下&#xff0c;“…...

24.98万起!理想汽车诚意之作,理想L6,年轻家庭的不二之选

2019年12月以来的累计交付量72万辆,理想汽车终于放出了大招,推出了家庭五座豪华SUV——理想L6。这款车有两个版本,Pro和Max,售价在24.98万到27.98万元之间。这辆车已经在4月份开始交付,是理想汽车进入30万以下市场的诚意之作。理想L6的外观延续了L系列的标志性星环设计,车…...

威兰达卖15.38万元,2.0L/2.5L,油耗5.7L

念寒记得不久前,有好几位车友问过我关于丰田威兰达的问题,其中最关心的就是这款车会不会降价促销,毕竟现在的合资燃油车确实不太好卖,所以我估计还有很多车友都是这样的一个想法。这不,千等万等降价终于被你们给等到了。近日,广汽丰田专门针对对威兰达推出了一项重磅优惠…...

Open3D-Geometry-2:Mesh网格的一些基础操作示例

0. 引言 Open3D 有一个名为 的 3D 三角形网格数据结构TriangleMesh。下面的代码显示了如何从ply文件中读取三角形网格并打印其顶点和三角形。 import open3d as o3d import numpy as npprint("Testing mesh in Open3D...") armadillo_mesh = o3d.data.ArmadilloMes…...

Google使用AI改进了 Sheets;开源视觉语言模型llama3v;开源情绪语音模型ChatTTS;

✨ 1: Google has improved Sheets with AI. Google 使用 AI 改进了 Sheets 您可以使用 Gemini 处理您的数据并将其变成老师。 优化您的数据 Gemini 了解您的数据并提出改进建议。 例如&#xff0c;它可以将重复数据转换为更实用的下拉框。 解释数据 通过单击双子座图标…...

探索Django 5: 从零开始,打造你的第一个Web应用

今天我们将一起探索 Django 5&#xff0c;一个备受开发者喜爱的 Python Web 框架。我们会了解 Django 5 的简介&#xff0c;新特性&#xff0c;如何安装 Django&#xff0c;以及用 Django 编写一个简单的 “Hello, World” 网站。最后&#xff0c;我会推荐一本与 Django 5 相关…...

网络原理-HTTPS协议

在前面说到HTTP中,我们通过抓包,可以看到许多信息内容,其中往往会包含一些敏感信息,这些都是明文传输,当我们的请求被黑客或者不法分子截获后,那就很危险了,因此衍生出了HTTPS协议来对传输数据进行加密。 一、加密原理 基本原理如下&#xff1a; 明文 密钥 > 密文 密文…...