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

C++ 多态、虚析构、模板类、常函数、虚继承、虚函数和纯虚函数相关知识和问题总结

1. C++ 中的多态

多态(Polymorphism)是面向对象编程中的一个重要特性,它允许使用相同的接口来表示不同的类型。由于派生类重写基类方法,然后用基类引用指向派生类对象,调用方法时候会进行动态绑定,这就是多态。

多态分为静态多态和动态多态:

1. 静态多态:编译器在编译期间完成的,编译器会根据实参类型来推断该调用哪个函数,如果有对应的函数,就调用,没有则在编译时报错。

静态多态(编译时多态)
  • 静态多态通过函数重载运算符重载模板实现。它在编译期间就决定了调用哪个函数。

函数重载示例

#include <iostream>
using namespace std;

class Print {
public:
    void display(int i) {
        cout << "Integer: " << i << endl;
    }

    void display(double f) {
        cout << "Float: " << f << endl;
    }
};

int main() {
    Print obj;
    obj.display(10);       // 调用int版本
    obj.display(3.14);     // 调用double版本
    return 0;
}

在这里,display函数被重载,不同的参数类型决定了在编译期哪个函数被调用。

2.动态多态:其实要实现动态多态,需要几个条件——即动态绑定条件:

        1. 虚函数。基类中必须有虚函数,在派生类中必须重写虚函数。

        2. 通过基类类型的指针或引用来调用虚函数。

动态多态(运行时多态)
  • 动态多态是通过虚函数实现的,在运行时决定调用哪个函数。
  • 使用基类指针或引用指向派生类对象,可以根据实际的对象类型调用相应的派生类的函数。

动态多态示例

#include <iostream>
using namespace std;class Base {
public:virtual void show() {  // 虚函数cout << "Base class show" << endl;}virtual ~Base() {}  // 虚析构函数,防止内存泄漏
};class Derived : public Base {
public:void show() override {cout << "Derived class show" << endl;}
};int main() {Base *bptr = new Derived();  // 基类指针指向派生类对象bptr->show();  // 动态绑定,调用 Derived 类的 show()delete bptr;   // 防止内存泄漏return 0;
}
  • 基类指针Base* bptr)实际指向了Derived对象,运行时根据对象的实际类型,调用了Derived类的show()方法。
总结
  • 静态多态:通过函数重载模板实现,在编译时决定调用哪个函数。
  • 动态多态:通过虚函数实现,依赖于运行时的动态绑定。

2. 为什么要虚析构,为什么不能虚构造?

虚析构的必要性
  • 当通过基类指针删除派生类对象时,如果基类析构函数不是虚函数,将不会调用派生类的析构函数,可能会导致派生类的资源没有被释放。

非虚析构的示例

#include <iostream>
using namespace std;class Base {
public:~Base() {cout << "Base destructor" << endl;}
};class Derived : public Base {
public:~Derived() {cout << "Derived destructor" << endl;}
};int main() {Base *bptr = new Derived();delete bptr;  // 只会调用Base的析构函数return 0;
}
  • 输出只会显示Base destructorDerived类的析构函数不会被调用,从而导致资源泄漏。

虚析构的解决方案

#include <iostream>
using namespace std;class Base {
public:virtual ~Base() {  // 虚析构函数cout << "Base destructor" << endl;}
};class Derived : public Base {
public:~Derived() {cout << "Derived destructor" << endl;}
};int main() {Base *bptr = new Derived();delete bptr;  // 调用Derived的析构函数return 0;
}
  • 输出会显示:
    Derived destructor
    Base destructor表明派生类的析构函数得到了正确调用,避免了资源泄漏。
为什么不能虚构造?
  • 构造函数用于初始化对象,而在构造期间,虚函数表还没有建立或准备好。构造函数依赖编译时的类型,不可能在构造时进行动态绑定。
  • 而且,构造函数负责创建对象的基类部分和派生类部分,如果构造函数是虚的,会产生语义上的混淆。
  • 虚析构:将可能会被继承的父类的析构函数设置为虚函数,可以保证当我们new一个子类,然后使用基类指针指向该子类对象,释放基类指针时可以释放掉子类的空间,防止内存泄漏。如果基类的析构函数不是虚函数,在特定情况下会导致派生类无法被析构。 1. 用派生类类型指针绑定派生类实例,析构的时候,不管基类析构函数是不是虚函数,都会正常析构 2. 用基类类型指针绑定派生类实例,析构的时候,如果基类析构函数不是虚函数,则只会析构基类,不会析构派生类对象,从而造成内存泄漏。为什么会出现这种现象呢,个人认为析构的时候如果没有虚函数的动态绑定功能,就只根据指针的类型来进行的,而不是根据指针绑定的对象来进行,所以只是调用了基类的析构函数;如果基类的析构函数是虚函数,则析构的时候就要根据指针绑定的对象来调用对应的析构函数了。 C++默认的析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存。
  • 不能虚构造: 1. 从存储空间角度:虚函数对应一个vtale,这个表的地址是存储在对象的内存空间的。如果将构造函数设置为虚函数,就需要到vtable中调用,可是对象还没有实例化,没有内存空间分配,如何调用。 2. 从实现上看,vtable在构造函数调用后才建立,因而构造函数不可能成为虚函数。

3. 模板类是在什么时候实现的?

模板类的定义和实现通常在头文件中一起写出,它们在编译时实例化,即编译器在遇到模板被使用时,才根据实际的模板参数生成相应的代码。这也是为什么模板函数的定义通常需要与声明放在同一个文件里。

模板类的示例

#include <iostream>
using namespace std;template<typename T>
class Box {
private:T value;
public:Box(T val) : value(val) {}void display() {cout << "Value: " << value << endl;}
};int main() {Box<int> intBox(10);         // 模板实例化为int类型Box<double> doubleBox(5.5);  // 模板实例化为double类型intBox.display();   // 输出:Value: 10doubleBox.display();  // 输出:Value: 5.5return 0;
}
  • 在编译时,根据Box<int>Box<double>的使用情况,编译器生成具体的Box<int>Box<double>代码。
总结
  • 模板在编译时进行实例化。
  • 模板代码通常写在头文件中,防止出现链接错误。

4. 构造函数为什么不能被声明为虚函数?

构造函数的主要任务是创建并初始化对象,而在构造函数中虚函数表(vtable)尚未建立。

  • 构造函数依赖编译时类型,即构造对象的类型在编译时就已经确定,不需要依赖虚函数机制。
  • 另一方面,虚函数机制依赖于虚表(vtable),而虚表是在构造函数执行完毕后才建立的。如果构造函数是虚的,虚表还没有准备好,因此无法进行动态绑定。

5. 什么是常函数,有什么作用?

常函数const成员函数)是在函数声明时,在函数名之后添加const关键字,表明该函数不会修改对象的任何成员变量。

常函数的示例

class MyClass {
private:
    int value;
public:
    MyClass(int v) : value(v) {}

    int getValue() const {  // 常函数
        return value;
    }

    void setValue(int v) {
        value = v;  // 非常函数,可以修改成员变量
    }
};
 

作用

  • 常函数的主要作用是保证对象的状态不会在函数中被改变,尤其是在使用const对象时。
  • 如果一个对象是常量(const),则只能调用常函数,无法调用非常函数。
int main() {const MyClass obj(10);// obj.setValue(20);  // 错误:不能调用非常函数cout << obj.getValue() << endl;  // 正确:常函数可以被const对象调用return 0;
}

6. 什么是虚继承,解决什么问题,如何实现?

虚继承的定义
  • 虚继承用于解决菱形继承问题。当多个派生类通过不同路径继承同一个基类时,会导致基类的成员在最终派生类中存在多份拷贝,造成数据冗余或歧义。虚继承可以确保最终派生类中只有一份基类的拷贝。
菱形继承问题的示例
#include <iostream>
using namespace std;class Base {
public:int value;
};class Derived1 : public Base {  // 非虚继承
};class Derived2 : public Base {  // 非虚继承
};class FinalDerived : public Derived1, public Derived2 {
public:void setValue(int v) {// value = v;  // 错误:编译器无法确定要修改 Derived1 还是 Derived2 的 value}
};

在这个例子中,FinalDerived类中有两个Base类的拷贝:一个来自Derived1,另一个来自Derived2。因此,value存在二义性。

虚继承解决菱形继承问题
#include <iostream>
using namespace std;class Base {
public:int value;
};class Derived1 : virtual public Base {  // 虚继承
};class Derived2 : virtual public Base {  // 虚继承
};class FinalDerived : public Derived1, public Derived2 {
public:void setValue(int v) {value = v;  // 不会有二义性,因为Base类只有一份拷贝}
};
  • 通过虚继承,FinalDerived类中只有一份Base类的拷贝,避免了菱形继承问题。

7. 虚函数和纯虚函数,以及实现原理

虚函数
  • 虚函数是使用virtual关键字声明的函数,允许派生类覆盖基类中的实现。虚函数支持运行时多态,通过动态绑定调用派生类的函数。
纯虚函数
  • 纯虚函数是一种特殊的虚函数,它在基类中没有定义,必须在派生类中实现。
  • 语法:将函数声明中的= 0表示为纯虚函数。

虚函数与纯虚函数示例

#include <iostream>
using namespace std;

class Base {
public:
    virtual void show() {  // 虚函数
        cout << "Base class show" << endl;
    }

    virtual void print() = 0;  // 纯虚函数
};

class Derived : public Base {
public:
    void show() override {
        cout << "Derived class show" << endl;
    }

    void print() override {
        cout << "Derived class print" << endl;
    }
};

int main() {
    Base *ptr = new Derived();
    ptr->show();  // 调用Derived类的show
    ptr->print();  // 调用Derived类的print
    delete ptr;
    return 0;
}

  • Base类中的print()函数是纯虚函数,派生类Derived必须提供实现。
实现原理

虚函数通过**虚函数表(vtable)**实现。每个包含虚函数的类都会维护一个虚函数表,表中存储了指向实际函数的指针。在运行时,编译器会根据对象的实际类型查找虚表,调用相应的函数。


8. 纯虚函数能实例化吗,为什么?派生类要实现吗,为什么?

纯虚函数的类不能实例化
  • 包含纯虚函数的类称为抽象类。由于纯虚函数没有实现,所以抽象类不能被实例化,否则在调用纯虚函数时会无从执行。
  • 示例:

    class AbstractClass {
    public:
        virtual void func() = 0;  // 纯虚函数
    };

    // AbstractClass obj;  // 错误:抽象类不能实例化
     

派生类必须实现纯虚函数
  • 如果派生类不实现基类中的纯虚函数,派生类也会变成抽象类,无法实例化。因此,派生类必须实现所有继承的纯虚函数。

9.虚函数纯虚函数区别

1. 虚函数(Virtual Function)
定义
  • 虚函数是基类中使用 virtual 关键字声明的成员函数。它允许派生类提供自己的实现,支持运行时多态
特点
  • 具有函数体:虚函数在基类中有完整的实现,派生类可以选择是否覆盖它。
  • 可选的覆盖:派生类可以重写虚函数,也可以不重写。如果派生类不提供自己的实现,调用该函数时会使用基类的版本。
  • 动态绑定:虚函数通过虚表(vtable)实现动态绑定,运行时根据实际对象的类型选择调用合适的函数版本。
示例
#include <iostream>
using namespace std;class Base {
public:virtual void show() {  // 虚函数cout << "Base class show" << endl;}
};class Derived : public Base {
public:void show() override {  // 重写虚函数cout << "Derived class show" << endl;}
};int main() {Base *b = new Derived();b->show();  // 调用Derived类的showdelete b;return 0;
}
  • 这里Base类中定义了虚函数 show()Derived 类重写了该函数。在运行时,通过基类指针调用的 show() 实际调用了 Derived 类的实现。
2. 纯虚函数(Pure Virtual Function)
定义
  • 纯虚函数是没有实现的虚函数,它在基类中声明,但不提供函数体,需要在派生类中实现。纯虚函数的声明使用 = 0 表示。
特点
  • 没有函数体:纯虚函数在基类中没有定义,仅作为接口存在。
  • 抽象类:包含纯虚函数的类是抽象类,不能被实例化。如果一个类包含一个或多个纯虚函数,它就无法创建对象,除非派生类实现所有的纯虚函数。
  • 必须被重写:所有派生类必须实现基类中的纯虚函数,否则派生类也将成为抽象类,无法实例化。
示例
#include <iostream>
using namespace std;class Base {
public:virtual void show() = 0;  // 纯虚函数
};class Derived : public Base {
public:void show() override {  // 实现纯虚函数cout << "Derived class show" << endl;}
};int main() {Base *b = new Derived();b->show();  // 调用Derived类的showdelete b;return 0;
}
  • 在此例中,Base 类定义了一个纯虚函数 show(),因此它是一个抽象类,不能实例化。但 Derived 类实现了该纯虚函数,因此可以创建 Derived 类的对象,并通过基类指针调用重写的函数。
3. 虚函数与纯虚函数的区别
比较维度虚函数(Virtual Function)纯虚函数(Pure Virtual Function)
函数体在基类中有实现,通常派生类可以选择重写或者使用基类实现。在基类中没有函数体,必须在派生类中实现。
类的类型包含虚函数的类不是抽象类,可以实例化。包含纯虚函数的类是抽象类,不能实例化。
派生类实现派生类可以重写虚函数,但不是必须的。派生类必须实现纯虚函数,除非它本身也是抽象类。
多态性支持运行时多态,基类指针或引用可以调用派生类的重写函数。也是运行时多态的一部分,依赖派生类的实现来调用函数。
使用目的提供一个可以被覆盖的默认实现,但允许派生类根据需要进行重写。定义一个接口,强制派生类提供自己的实现。
实现原理通过虚函数表(vtable)实现动态绑定。也是通过虚函数表(vtable)实现动态绑定,但必须有实现函数。
4. 使用场景和设计目的
  • 虚函数:当你希望在基类中提供函数的默认行为,但允许派生类根据需要选择重写时,可以使用虚函数。这种设计允许部分多态行为,而不强制所有派生类都必须实现该函数。

  • 纯虚函数:当你希望基类只定义接口,并且要求所有派生类都必须提供自己的实现时,使用纯虚函数。这种设计常见于抽象基类中,它们定义了派生类的共同行为接口,但不提供具体实现。


5. 总结
  • 虚函数是可以在基类中提供实现的函数,派生类可以选择重写它们,也可以直接使用基类的实现。
  • 纯虚函数定义了一个必须由派生类实现的接口,它没有实现,派生类必须提供它的定义,否则它们也将是抽象类,无法实例化。

相关文章:

C++ 多态、虚析构、模板类、常函数、虚继承、虚函数和纯虚函数相关知识和问题总结

1. C 中的多态 多态&#xff08;Polymorphism&#xff09;是面向对象编程中的一个重要特性&#xff0c;它允许使用相同的接口来表示不同的类型。由于派生类重写基类方法&#xff0c;然后用基类引用指向派生类对象&#xff0c;调用方法时候会进行动态绑定&#xff0c;这就是多态…...

计算机组成原理一句话

文章目录 计算机系统概述存储系统指令系统 计算机系统概述 指令和数据以同等地位存储在存储器中&#xff0c;形式上没有差别&#xff0c;但计算机应能区分他们。通过指令周期的不同阶段。 完整的计算机系统包括&#xff0c;1&#xff09;软件系统&#xff1a;程序、文档和数据&…...

【Linux】僵尸进程和孤儿进程

一、僵尸进程 何为僵尸进程&#xff1f; 在 Unix/Linux 系统中&#xff0c;正常情况下&#xff0c;子进程是通过父进程创建的&#xff0c;且两者的运行是相互独立的&#xff0c;父进程永远无法预测子进程到底什么时候结束。当一个进程调用 exit 命令结束自己的生命时&#xff…...

Patchcore运行过程

论文github地址&#xff1a;https://github.com/amazon-science/patchcore-inspection 平台&#xff1a;autodl云服务器 1.将下载的代码上传到autodl-tmp/PatchCore里面解压&#xff0c;将数据集上传path_to_mvtec_folder/mvtec里&#xff0c;目录结构如图 2.安装依赖 cd au…...

一小时快速入门Android GPU Inspector

本文介绍如何使用 Android GPU Inspector (AGI) 对Android 应用进行系统性能分析和帧性能分析 。面向熟悉Android图形的开发者。 待分析应用需要的前置条件 (1) 将应用设置为可调试状态 <application [...] android:debuggable"true">&#xff08;2&#xff09…...

二叉树展开为链表

二叉树展开为链表 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同…...

基于SpringBoot+Vue+uniapp微信小程序的教学质量评价系统的详细设计和实现

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…...

【二刷hot100】day 4

终于有时间刷刷力扣&#xff0c;求实习中。。。。 目录 1.最大子数组和 2.合并区间 3.轮转数组 4.除自身以外数组的乘积 1.最大子数组和 class Solution {public int maxSubArray(int[] nums) {//就是说可以转换为计算左边的最大值&#xff0c;加上中间的值&#xff0c…...

10.22学习

1.求余 在C语言中&#xff0c;求余操作是通过取模运算符 % 来实现的。取模运算符会返回两个数相除后的余数。对于正数和负数的除法&#xff0c;求余的结果会有所不同&#xff0c;但 % 运算符总是返回被除数的符号。 下面是一个简单的例子&#xff0c;展示如何使用 % 运…...

【不要离开你的舒适圈】:猛兽才希望你落单,亲人总让你回家,4个维度全面构建舒适圈矩阵

单打独斗的英雄时代已经落幕 抱团取暖才是社会寒冬的良策 自然界中&#xff0c;每个物种都占据着自己的领地和生存空间。 生态位的差异决定了它们的生存方式&#xff0c;一旦离开领地&#xff0c;失去群体的庇护&#xff0c;就会沦为野兽的美餐。 人类社会同样存在隐形圈层…...

OpenIPC开源FPV之Channel配置

OpenIPC开源FPV之Channel配置 1. 源由2. 现象3. 硬件3.1 模拟频点3.2 数字频点2.4GHz频段频点表格 (802.11b/g/n):5GHz频段频点表格 (802.11a/n/ac): 4. 分析5. 实验6. 参考资料 1. 源由 无线信号&#xff0c;传输过程中不可避免都会受到干扰。同时&#xff0c;由于在一个开放…...

UG NX12.0建模入门笔记:1.0 UG NX12.0安装教程

一、如何关闭防火墙&#xff1f; 提示&#xff1a;安装软件之前&#xff0c;建议先 关闭防火墙和杀毒软件&#xff01;&#xff01;&#xff01; 文章目录 一、如何关闭防火墙&#xff1f;二、UG NX12.0安装包三、UG NX12.0安装教程1.新建文件夹2.安装JAVA环境3.安装许可证管理…...

【C++】踏上C++学习之旅(三):“我“ 与 “引用“ 的浪漫邂逅

文章目录 前言1. "引用"的概念1.1 "引用"的语法 2. "引用"的特性3. "引用"的使用场景3.1 "引用"做参数3. 2 "引用"做返回值3.2.1 "引用"做返回值时需要注意的点 4. 常引用5. "引用"在底层的实…...

中间件之Seata

一、引言 在微服务架构日益盛行的今天&#xff0c;分布式事务成为了一个必须面对和解决的问题。传统的本地事务已经无法满足分布式环境下的数据一致性需求&#xff0c;因此分布式事务解决方案应运而生。Seata作为一款开源的分布式事务中间件&#xff0c;以其高性能、易用性和灵…...

MySQL 异常: “Host ‘xxx‘ is not allowed to connect to this MySQL server“

update user set host % where user root; FLUSH PRIVILEGES; 这两行代码就行...

c语言中字符串函数strlen,strcmp,strcpy,srtcat,strncpy,strncat,strncmp

1.strlen的使用和模拟实现 strlen 用来求字符串的长度&#xff0c;统计\0之前字符的个数。 模拟实现1&#xff1a;计数参数法 #include<stdio.h> #include<assert.h> size_t my_strlen(char* str) {int count0;assert(str);//assert断言是判断是字符串不能为空w…...

携程线下一面,面试内容:

面试时间&#xff1a;2024/9/12 • 实例方法和静态方法有什么不一样? • Java中的异常有哪几类?分别怎么使用? • 常用的集合类有哪些?比如List如何排序? • ArrayList和LinkedList内部的实现大致是怎样的?他们之间的区别和各自适应的场景是什么? • 内存溢出是怎么…...

DeepL翻译:全世界最准确的翻译

DeepL翻译是一款高质量的机器翻译工具&#xff0c;以下从产品描述、产品特色、适用人群、适用场景四个方面对其进行介绍&#xff1a; 体验地址&#xff1a;DeepL翻译&#xff1a;全世界最准确的翻译 产品描述 DeepL是一家德国公司&#xff0c;以其高质量的机器翻译服务而闻名…...

15分钟学Go 实战项目一:命令行工具

实战项目一&#xff1a;命令行工具 1. 引言 命令行工具是开发者常用的工具之一&#xff0c;它可以帮助用户通过命令行界面对程序进行控制和交互。在这节中&#xff0c;我们将创建一个简单的命令行工具&#xff0c;以帮助你理解Go语言的基本语法和如何处理命令行输入。在这个过…...

lesson02 作业

lesson02-01作业 小红的体重是 m 千克&#xff0c;她想知道自己的体重在磅&#xff08;1 千克约等于 2.20462 磅&#xff09;是多少 输入描述 输入一个整数表示小红的标准体重m(kg) 输出描述 输出一个整数表示转换后的磅值n 磅 示例 输入&#xff1a; 50 输出&#xff1a…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)

目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 ​编辑​编辑 UDP的特征 socke函数 bind函数 recvfrom函数&#xff08;接收函数&#xff09; sendto函数&#xff08;发送函数&#xff09; 五、网络编程之 UDP 用…...

CSS3相关知识点

CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...

EEG-fNIRS联合成像在跨频率耦合研究中的创新应用

摘要 神经影像技术对医学科学产生了深远的影响&#xff0c;推动了许多神经系统疾病研究的进展并改善了其诊断方法。在此背景下&#xff0c;基于神经血管耦合现象的多模态神经影像方法&#xff0c;通过融合各自优势来提供有关大脑皮层神经活动的互补信息。在这里&#xff0c;本研…...