C++笔记:C++中的重载

news2024/10/7 14:29:59

重载的概念

一.函数重载

代码演示例子:


#include<iostream>
using namespace std;

//函数名相同,在是每个函数的参数不相同
void output(int x) {
    printf("output int : %d\n", x);
    return ;
}

void output(long long x) {
    printf("output long long : %llX\n", x);
    return ;
}

void output(const char *s) {
    if (!s) {
        printf("output string : nullptr\n");
        return ;
    }
    printf("output string : %s\n", s);
    return ;
}

void output(int x, int y) {
    printf("output double int : %d, %d\n", x, y);
    return ;
}
//如果调用这个函数时,没有传入参数3,也就是c
//那么c的默认值就为123,并且程序不会编译不通过
void output(int a, char b, int c = 123) {
    printf("output a = %d, b = %c, c = %d\n", a, b, c);
    return ;
}

//如果这里没有第三个参数,那么就会造成编译报错
//因为没有办法通过返回值类型进行区分重载类型
//也就是没有办法区分和上面的double int进行区分
const char *output(int a, int b, char c) {
    printf("output a = %d, b = %d, c = %c\n", a, b, c);
    return "yes";
}


int main() {
    output(3);//这里匹配的是int类型的output
    //在数字后面加上LL 表示这个数字是longlong类型
    output(3LL);//这里匹配的是longlong类型的output
    output("hello world");//匹配参数为char *的output
    output(3, 4);//匹配参数为两个int类型的output
    output(3LL, 4);//近似匹配了两个int类型的output
    //下面这个output(NULL),他会匹配到int类型
    //NULL可以表示成0值
    //然后它也可以表示成一个地址,然后它又是0值的地址,地址有64位也就是8字节,那他也会匹配long long类型
    //然后还表示一个空地址,还会匹配到char *类型
    //output(NULL);
    //而在C++中 nullptr只表示空地址,这样他就会精确匹配对应的函数
    output(nullptr);
    output(12, 'p');
    cout << output(3, 4, 'c') << endl;
    return 0;
}

然后如果output(NULL)那行代码没有注释掉,那么就会出现,注释说明的情况,无法匹配造成歧义:

对于成员函数重载和普通函数的重载一样,我就不用代码进行演示了。

二.运算符重载

不能重载的运算符:

类外:

参考代码:

#include <iostream>
#include <cstdio>
using namespace std;

class Point {
public :
    Point() : x(0), y(0), output_width(0) {}
    Point(int x, int y) : x(x), y(y), output_width(0) {}
private :
    int x, y;
    int output_width;
    //利用友元进行解决私有成员属性的访问问题
    friend ostream &operator<<(ostream &out, const Point &p);
    friend int operator*(const Point &, const Point &);
    friend Point operator+(const Point &, int );
    friend double operator*(const Point &, double );
    friend double operator*(double , const Point &);
    friend Point &operator-(Point &, int x) ;
    friend Point &operator-(Point &, Point &) ;
    friend Point &operator-(Point &, const char *) ;
};
//ostream类型就像cout的对象的类型
//加上const为了同时支持const和非const限定的对象
ostream &operator<<(ostream &out, const Point &p) {
    out << "("  << p.x << ", " << p.y << ")";
    return out; 
}

int operator*(const Point &p1, const Point &p2) {
    return p1.x * p2.x + p1.y * p2.y;
}

Point operator+(const Point &p1, int x) {
    Point p(p1.x + x, p1.y + x);
    return p;
}

double operator*(const Point &p1, double x) {
    return p1.x * x + p1.y * x;
}

double operator*(double x, const Point &p1) {
    //这里他调用的就是上面运算符重载的方法
    return p1 * x;
}

Point &operator-(Point &p, int x) {
    p.output_width = x; 
    return p;
}

Point &operator-(Point &p1, Point &p2) {
    char str[100] = {0};
    snprintf(str, 99, "(%%%dd, %%%dd)", p1.output_width, p1.output_width);
    printf(str, p2.x, p2.y);
    return p1;
}

Point &operator-(Point &p, const char *s) {
    printf("%s", s);
    return p;
}

Point &operator^(Point &p1, const Point &p2) {
     
    return p1;
}

Point &operator^(Point &p1, int x) {

    return p1;
}

int main() {
    Point p1(5, 6), p2(3, 6), p3(6, 9), p4(10, 12);
    //cout他也不认识我们创建的Point类
    //如果要对cout进行对p1进行输出
    //那么我们就要对<<这个左移运算符进行重载
    cout << p1 << endl;
    //这里对运算符的重载可以不用实现和我一样的,可以通过自己的想象然后来实现
    //然后实现的结果和自己的想象的需要是一样的结果
    cout << p1 * p2 << endl;
    cout << p1 * 2.3 << endl;
    cout << 2.3 * p1 << endl;
    cout << p1 + 5 << endl;
    //实现效果
    //p1 - 6设置输出的位宽为6
    //- p2 输出p2的值,并且输入的位宽为p1的位宽
    //- "\n" 换行
    p1 - 6 - p2 - "\n";
    return 0;
}

练习:

        实现下面的代码:

    Point p1(5, 6), p2(3, 6), p3(6, 9), p4(-2, -4);
    cout << p1 << p2 << p3 << p4 << endl;
    //^运算符将每个类中的成员属性x,y输出到一个坐标轴中
    //^1时打印出这个坐标轴
    p1^p2^p3^p4^1;

参考代码:

#include <iostream>
#include <cstdio>
using namespace std;

#define MAX_N 20

class Point {
public :
    Point() : x(0), y(0) {}
    Point(int x, int y) : x(x), y(y) {}
    ~Point() {}
    static void init_x_y_axis() {
        for (int i = 0; i < MAX_N; i++) {
            Point::x_y_axis[i] = new int[MAX_N + 5];
        }
        return ;
    }
    static void set_x_y_axis(int x, int y) {
        if (x_y_axis[x + MAX_N / 2][y + MAX_N / 2]) return ;
        x_y_axis[x + MAX_N / 2][y + MAX_N / 2] = 1;
        return ;
    }
    void output() {
        cout << sizeof(Point::x_y_axis[0]) << endl;
        cout << sizeof(Point::x_y_axis) << endl;
    }

    friend Point &operator^(Point &, Point &);
    friend Point &operator^(Point &, int);
    friend ostream &operator<<(ostream &, const Point &);
private :
    int x, y;
    //创建一个类属性
    //用来当作坐标轴
    static int **x_y_axis;
};

int **Point::x_y_axis = new int*[MAX_N + 5];


Point &operator^(Point &p1, Point &p2) {
    //将每个对象的x,y输出到坐标轴中
    Point::set_x_y_axis(p1.x, p1.y);
    Point::set_x_y_axis(p2.x, p2.y);
    return p1;
}

Point &operator^(Point &p1, int num) {
    //我们要求的是^1才打印
    if (num != 1) return p1;
    for (int y = MAX_N / 2; y > -MAX_N / 2; y--) {
        for (int x = -MAX_N / 2; x < MAX_N / 2; x++) {
            !x && y && printf("%3d", y);
            if (!y) {
                printf("%3d", x);
            } else {
                if (Point::x_y_axis[x + (MAX_N / 2)][y + (MAX_N / 2)]) {
                    printf("%3c", '*');
                }
                else if (x) printf("%3c", ' ');
            }
        }
        putchar(10);
    }
    return p1;
}

ostream &operator<<(ostream &out, const Point &p1) {
    out << "p("  << p1.x << ", " << p1.y << ")" << endl;
    return out;
}

int main() {
    Point::init_x_y_axis();
    Point p1(5, 6), p2(3, 6), p3(6, 9), p4(-2, -4);
    cout << p1 << p2 << p3 << p4 << endl;
    //^运算符将每个类中的成员属性x,y输出到一个坐标轴中
    //^1时打印出这个坐标轴
    p1^p2^p3^p4^1;
    return 0;
}

实现效果:

        实现结果可以和我不一样,但是一定要实现你自己的想法,C++的语法就是非常的灵活并且也非常容易出错,所以这才是C++的难处.

        注意:学习C++是学习C++的设计模式。

类内:

    对于下面的运算符,只能再类内中重载,但是不是意思是只能重载这些运算符,对于类外可以重载的运算符,类内一样也可以重载

在说类内的运算符之前说一个知识点左值右值: 

左值右值

带入代码理解:

#include<iostream>
using namespace std;

#define LEFT_OR_RIGHT(expr) {\
    printf("expr : %s\n", #expr);\
    left_or_right(expr);\
    printf("\n");\
}

void left_or_right(int &x) {
    printf("left value : %d\n", x);
    return ;
}

void left_or_right(int &&x) {
    printf("right value : %d\n", x);
    return ;
}


int main() {
    int a = 123;
    //a可以通过单一变量a访问
    //那么他就是左值
    LEFT_OR_RIGHT(a);
    //a + 1是中间产生临时的一个值
    //那么他无法通过单一变量进行访问到
    //那他就是一个右值
    //因为在过了下面这行代码后,我们没有办法进行通过单一变量进行访问到它
    LEFT_OR_RIGHT(a + 1);
    //任何字面量的值都是右值
    LEFT_OR_RIGHT(123);
    //这里a++你带入进去的是a的值
    //然后带入后,a进行了a += 1
    //那么在这行代码之后你无法通过单一变量去访问到之前的a值
    //那么它就是右值
    LEFT_OR_RIGHT(a++);
    //++a带入的是 a += 1的值
    //在这行代码之后,它可以通过单一变量a去访问到这个值
    //那他就是左值
    LEFT_OR_RIGHT(++a);
    //a += 2同理它可以通过变量a去访问到这个值
    LEFT_OR_RIGHT(a += 2);
    return 0;
}

执行结果,和我代码注释推断的结果是一样的:

然后下一个版本:

#include<iostream>
using namespace std;

#define LEFT_OR_RIGHT(expr) {\
    printf("expr : %s\n", #expr);\
    left_or_right(expr);\
    printf("\n");\
}

void left_or_right(int &&, int);

void left_or_right(int &x, int flag = 1) {
    printf("left value : %d\n", x);
    if (flag) left_or_right(x, 0);
    return ;
}

void left_or_right(int &&x, int flag = 1) {
    printf("right value : %d\n", x);
    if (flag) left_or_right(x, 0);
    return ;
}


namespace test1 {
int main() {
    int a = 123;
    //a可以通过单一变量a访问
    //那么他就是左值
    LEFT_OR_RIGHT(a);
    //a + 1是中间产生临时的一个值
    //那么他无法通过单一变量进行访问到
    //那他就是一个右值
    //因为在过了下面这行代码后,我们没有办法进行通过单一变量进行访问到它
    LEFT_OR_RIGHT(a + 1);
    //任何字面量的值都是右值
    LEFT_OR_RIGHT(123);
    //这里a++你带入进去的是a的值
    //然后带入后,a进行了a += 1
    //那么在这行代码之后你无法通过单一变量去访问到之前的a值
    //那么它就是右值
    LEFT_OR_RIGHT(a++);
    //++a带入的是 a += 1的值
    //在这行代码之后,它可以通过单一变量a去访问到这个值
    //那他就是左值
    LEFT_OR_RIGHT(++a);
    //a += 2同理它可以通过变量a去访问到这个值
    LEFT_OR_RIGHT(a += 2);
    return 0;
}
}

int main() {
    //test1::main();
    left_or_right(123);
    return 0;
}

执行结果:

为什么呢,123先调用右值引用没有问题吧,然后现在flag为1,需要再次调用left_or_right()函数,然后呢现在他的参数为x而不是123,那么在执行完成调用函数这句代码之后,我还是可以通过x进行访问到这个值,在右值引用这个函数的作用域里面这个x是持久态,我调用完成这个函数我是可以进行访问到的,所以第二次调用就会调用左值引用。

那么问题来了,我想保持当前的右值引用如何操作呢:

现在去理解move函数就是把move函数里的参数强制转换为右值,如果你想了解的更深可以自己看看move函数的原型,以及具体如何操作的。  

if (flag) left_or_right(move(x), 0);

改完这行代码后执行结果:

还有一种方式:

forward<>()函数,forward 函数通常用于完美转发,用于将参数原封不动地传递给另一个函数,保持参数的值类别不变。

if (flag) left_or_right(forward<int &&>(x), 0);

forward在这句代码的作用就是将x作为右值引用作为传入参数,但是x他还是左值引用。

但是move是将x变为了右值引用。

移动构造 

那么说完左值右值,那么对于构造函数还有一种形式,叫做移动构造:

代码演示:

#include <iostream>
#include <cassert>
#include <ctime>
using namespace std;

class Array {
public :
    Array(int n) : n(n), arr(new int[n]) {
        cout << "array default constructor " << arr << endl;
    }
    Array(const Array &a) : n(a.n), arr(new int[n]) {
        cout << "copy array constructor " << arr << endl;
        for (int i = 0; i < n; i++) arr[i] = a[i];
        return ;
    }
    //再函数调用时,如果没有返回值优化
    //那么调用func()函数时,会先默认构造a,
    //默认构造返回值的隐匿对象,这里创建了新的空间
    //然后a拷贝给匿名对象
    //然后又将匿名拷贝给b对象,有创建了新空间
    //而移动构造,直接将第一次a创建的空间直接给匿名对象
    //匿名对象又通过移动构造将创建的空间给b对象,省去了中间创建新空间的步骤和释放空间的步骤
    Array(Array &&a) : n(a.n), arr(a.arr) {
        cout << "move constructor" << arr << endl;
        a.arr = nullptr;
        a.n = 0;
        return ;
    }
    //这里为什么要返回int &
    //因为你在访问该位置时,又可以能会将该位置进行赋值
    //所以需要返回int &
    int &operator[](int ind) const{
        assert(ind >= 0 && ind < n);
        return arr[ind];
    }
    
    void output(const char *frm) {
        for (int i = 0; i < n; i++) {
            printf(frm, i, arr[i]);
        }
    }
    ~Array() {
        if (arr) delete[] arr;
        cout << "array disconstructor " << arr << endl;
        return ;
    }
private :
    int n;
    int *arr;
};

Array func() {
    int n = 7;
    Array a(n);
    for (int i = 0; i < n; i++) {
        a[i] = i;
    }
    return a;
}

int main() {
    srand(time(0));
    int n = 10;
    printf("a = ");
    Array a(n);
    for (int i = 0; i < n; i++) {
        a[i] = rand() % 100;
    }
    a.output("a[%d] = %d\n");
    Array b = func();
    b[0] = 999;
    b.output("b[%d] = %d\n");
    //如果对于a对象不用了,想将a对象所有的东西给c对象
    //那么就可以调用移动构造,使用move函数将a对象传入时变为右值
    Array c(move(a));
    c.output("c[%d] = %d\n");
    return 0;
}

 类内的运算符重载代码演示:
 前后++代码演示:
#include<iostream>
using namespace std;

class Point {
public :
    Point(int x, int y) : x(x), y(y) {}
    Point(const Point &a) : x(a.x), y(a. y) {}
    //+重载, p1 + p2 就是 p1.x + p2.x, p1.y + p2.y
    //因为返回的是一个新的值,所以是右值,返回值类型就不是引用,也就是不是左值
    Point operator+(const Point &p) {//他这里是成员方法,比如它可以访问this指针
        Point ret(x + p.x, y + p.y);
        return ret;
    }
    //由于是前++,就不需要参数
    //前++返回的是左值,所以返回值类型也是左值
    //返回的对象也是本身
    Point &operator++() {
        cout << "++class" << endl;
        this->x += 1, this->y += 1;
        return *this;
    }
    //后++是一个右值,在演示左值和右值代码中有示例
    //那么返回的是一个新的值,所以返回值类型也是右值,而不是左值引用
    //参数列表中有参数,就是后++
    Point operator++(int) {
        cout << "class++" << endl;
        Point ret(*this);
        //代码设计逻辑和技巧
        ++(*this);
        return ret;
    }
    friend ostream &operator<<(ostream &out, const Point &p);
private :
    int x, y;
};

ostream &operator<<(ostream &out, const Point &p) {
    out << "(" << p.x << ", " << p.y << ")";
    return out;
}


int main() {
    Point a(1, 2), b(3, 4);
    cout << "a : " << a << endl;
    cout << "b : " << b << endl;
    cout << a + b << endl;
    //这样去调用运算符重载的函数和上行代码执行效果一样
    cout << a.operator+(b) << endl;
    cout << "++a : " << ++a << endl;
    cout << "b++ : "<< b++ << endl;
    cout << "b : "<< b << endl;
    return 0;
}

=赋值运算符重载代码演示:


#include<iostream>
using namespace std;

class A {
public :
    A() {
        cout << "default constructor " << this << endl;
    }
    A(const A &a) {
        cout << "copy constructor " << this << endl;
    }
    A(const A &&a) {
        cout << "move constructor " << this << endl;
    }
    //对于=重载
    A &operator=(const A &a) {
        //new关键字的原地构造
        //在this指针这块位置调用拷贝构造
        //this指针指向的就是下面的对象c
        new(this) A(a);
        cout << "operator= " << this << endl;
        return *this;
    }
    A &operator=(A &&a) {
        new(this) A(move(a));
        cout << "operator= " << this << endl;
        return *this;
    }
};


int main() {
    A a, c, d;
    A b = a;
    c = a;
    d = move(a);
    cout << "a = " << &a << endl;
    cout << "b = " << &b << endl;
    cout << "c = " << &c << endl;
    cout << "d = " << &d << endl;
    return 0;
}
[]、->、()运算符重载代码演示:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

class Array_Object {
public :
    int operator[](int ind) {
        return 2 * ind;
    }
};

class Function_Object {
public :
    int operator()(int x) {
        return 2 * x; 
    }
};

class Point {
public :
    Point(int x, int y) : x(x), y(y){
        printf("x = %d, y = %d\n", x, y);
    }
    int x, y;
};

class Point_Object {
public :
    Point_Object() : p(new Point(rand() % 100, rand() % 100)) {}
    Point *operator->() {
        return p; 
    }
    ~Point_Object() {
        delete p;
    }
private :
    Point *p;
};

int main() {
    srand(time(0));
    Array_Object arr;
    Function_Object fun;
    Point_Object p;
    cout << p->x << " " << p->y << endl;
    for (int i = 0; i < 10; i++) {
        cout << "arr[" << i << "]" << arr[i] << endl;
    }
    for (int i = 0; i < 10; i++) {
        cout << "fun(" << i << ")" << fun(i) << endl;
    }
    return 0;
}

 

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

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

相关文章

TiDB 6.x 新特性解读 | Collation 规则

对数据库而言&#xff0c;合适的字符集和 collation 规则能够大大提升使用者运维和分析的效率。TiDB 从 v4.0 开始支持新 collation 规则&#xff0c;并于 TiDB 6.0 版本进行了更新。本文将深入解读 Collation 规则在 TiDB 6.0 中的变更和应用。 引 这里的“引”&#xff0c;…

小程序线多点路图绘制

需求 当接口返回一连串地图坐标&#xff0c;需要根据这些坐标串联起来&#xff0c;形成一个线路图&#xff08;本次使用步行导航线路图&#xff09;。 思路 首先优先想到使用小程序Map组件的polyline属性去进行展示。但是我们发现直接使用该属性进行坐标绘制画出来的数据都是…

李沐56_门控循环单元——自学笔记

关注每一个序列 1.不是每个观察值都是同等重要 2.想只记住的观察需要&#xff1a;能关注的机制&#xff08;更新门 update gate&#xff09;、能遗忘的机制&#xff08;重置门 reset gate&#xff09; !pip install --upgrade d2l0.17.5 #d2l需要更新import torch from tor…

10.MMD 室内场景导入背景视频和灯光

导入背景视频 1. 导入人物和场景 场景是Akali’s room&#xff0c;可以在墙壁上添加视频 先添加主场景 2. 修改视频文件格式 在背景里选择导入背景视频文件 需要将mp4视频格式转化为AVI格式 方法一 先将视频导入格式工厂 点击配置 将视频编码改成DivX 再开始处理 …

高效率Python开发工具PyCharm v2024.1——更新AI Assistant功能

JetBrains PyCharm是一种Python IDE&#xff0c;其带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具。此外&#xff0c;该IDE提供了一些高级功能&#xff0c;以用于Django框架下的专业Web开发。 立即获取PyCharm v2024.1正式版(Q技术交流&#xff1a;909157416&…

利用Spring中的SchedulingConfigurer实现数据库配置化定时任务

目录 1.利用Scheduled来实现传统的定时任务 2.两者的区别 3.Spring中的SchedulingConfigurer来拓展定时任务的灵活性 1&#xff09;UrTaskConfig 2&#xff09;TaskMain 3&#xff09;BaseTask 4&#xff09;效果 &#xff08;1&#xff09;插入配置定时任务的sql语句 …

参数传递 的案例

文章目录 12 1 输出一个int类型的数组&#xff0c;要求为&#xff1a; [11,22,33,44,55] package com.zhang.parameter; //有关方法的案例 public class MethodTest3 {public static void main(String[] args) {//输出一个int类型的数组&#xff0c;要求为&#xff1a; [11,…

UE4网络图片加载库(带内存缓存和磁盘缓存)

UE4网络图片加载库,带内存缓存和磁盘缓存,支持自定义缓存大小,支持蓝图和C++代码调用 1、调用示例 2、对外暴露函数 3、源代码-网络模块 KeImageNet.h // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreM…

在控制台实现贪吃蛇

在控制台实现贪吃蛇 前备知识Win32APICOORD这个结构体的声明如下&#xff1a;GetStdHandle 函数GetConsoleCursorInfo 函数SetConsoleCursorInfo 函数 SetConsoleCursorPosition 函数getAsyncKeyState 函数 控制台窗口的大小以及字符打印介绍控制台中的坐标宽字符及本地化介绍s…

的记忆:pandas(实在会忘记,就看作是一个 Excel 表格,或者是 SQL 表,或者是字典的字典。)

pandas 是一个开源的 Python 数据分析库&#xff0c;它提供了快速、灵活和富有表现力的数据结构&#xff0c;旨在使“关系”或“标记”数据的“快速分析、清洗和转换”变得既简单又直观。pandas 非常适合于数据清洗和转换、数据分析和建模等任务。以下是 pandas 的基本概念和主…

使用 Flutter 打造引人入胜的休闲游戏体验

作者 / Zoey Fan 去年&#xff0c;Flutter 休闲游戏工具包进行了一次重大更新。近期在旧金山举办的游戏开发者大会 (GDC) 上&#xff0c;Flutter 首次亮相。GDC 是游戏行业的顶级专业盛会&#xff0c;致力于帮助游戏开发者不断提升开发技能。欢迎您继续阅读&#xff0c;了解开发…

Redis(四) 主从、哨兵、集群环境搭建

结合前三期 Redis(一) Redis简介(Redis(一) Redis简介-CSDN博客) Redis(二) 可编程性(Redis(二) 可编程性-CSDN博客) Redis(三) 事务与发布订阅(Redis(三) 事务与发布订阅-CSDN博客) 目录 1.0 Redis主从 1.1 Redis 主从结构的基本原理和工作方式 1.2 Redis 主从结构的好处 …

经典案例|使用Supabase解决可视化大屏项目的常见问题

敏博科技专业致力于应急管理行业&#xff0c;提供以物联网技术和感知预警算法模型为核心的先进产品和解决方案。应急管理行业的业务非常繁多和复杂&#xff0c;很多时候都需要在短时间内交付出稳定高效的业务系统。如下两张图某市的安全生产监测预警系统 MemFire Cloud应用开…

图像处理之模板匹配(C++)

图像处理之模板匹配&#xff08;C&#xff09; 文章目录 图像处理之模板匹配&#xff08;C&#xff09;前言一、基于灰度的模板匹配1.原理2.代码实现3.结果展示 总结 前言 模板匹配的算法包括基于灰度的匹配、基于特征的匹配、基于组件的匹配、基于相关性的匹配以及局部变形匹…

Maven的下载和环境变量的配置

1下载 maven官网https://maven.apache.org/index.html点击Download 这个是Windows的下载版本&#xff0c;一般是最新的版本&#xff0c; 老的版本下载 以下是对应的老版本下载链接 下载好后是一个压缩包的形式 点击他进行解压到想放的文件夹中&#xff0c;&#xff08;一般不…

设计模式-00 设计模式简介之几大原则

设计模式-00 设计模式简介之几大原则 本专栏主要分析自己学习设计模式相关的浅解&#xff0c;并运用modern cpp 来是实现&#xff0c;描述相关设计模式。 通过编写代码&#xff0c;深入理解设计模式精髓&#xff0c;并且很好的帮助自己掌握设计模式&#xff0c;顺便巩固自己的c…

【神经网络基础辨析】什么是神经网络的主干(backbone)、颈部(neck)和头部(head)网络

在神经网络中&#xff0c;通常将网络分为三个部分&#xff1a;骨干网络&#xff08;Backbone&#xff09;、颈部网络&#xff08;Neck&#xff09;、和头部网络&#xff08;Head&#xff09;。 骨干网络&#xff08;Backbone&#xff09; 骨干网络通常是神经网络的主要部分&a…

探索设计模式的魅力:主从模式与AI大模型的结合-开启机器学习新纪元

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨欢迎加入探索主从模式与AI大模型之旅✨ &#x1f31f;Hey, tech enthusiasts! 你是否还在追…

【嵌入式AI部署神经网络】STM32CubeIDE上部署神经网络之指纹识别(Pytorch)——篇一|环境搭建与模型初步部署篇

前言&#xff1a;本篇主要讲解搭建所需环境&#xff0c;以及基于pytorch框架在stm32cubeide上部署神经网络&#xff0c;部署神经网络到STM32单片机&#xff0c;本篇实现初步部署模型&#xff0c;没有加入训练集与验证集&#xff0c;将在第二篇加入。篇二详细讲解STM32CubeIDE上…

PHP之内置web服务器

1. 前言 PHP从5.4开始&#xff0c;就提供了一个内置的web服务器。 这个主要是用来做本地的开发测试用的&#xff0c;不能用于线上环境。 将PHP的安装路径配置到电脑的系统环境变量Path中&#xff0c;下图是win7&#xff0c;win10中会看的更清楚 2. 进入项目目录&#xff0c;执…