【C++笔记】类和对象的深入理解(三)

【C++笔记】类和对象的深入理解(三)

🔥个人主页大白的编程日记

🔥专栏C++笔记


文章目录

  • 【C++笔记】类和对象的深入理解(三)
    • 前言
    • 一.日期类的实现
      • 1.1声明和定义分离
      • 1.2日期类+=整数
      • 1.3日期类+整数
      • 1.4日期类-=整数
      • 1.5日期类-日期
      • 1.6复用对比
      • 1.7日期类==日期类
      • 1.8日期类<日期类
      • 1.9比较复用
      • 1.10前置和后置
      • 1.11日期类-日期类
      • 1.12日期类IO
    • 二.取地址运算符重载
      • 2.1const成员函数
      • 2.2取地址运算符重载
    • 三.再探构造函数
    • 四.类型转换
    • 五.static成员
    • 六.友元
    • 七.内部类
    • 八.匿名对象
    • 后言

前言

哈喽,各位小伙伴大家好!上期我们讲了类和对象的更深入的内容。今天我们就给类和对象收尾。话不多说,咱们进入正题!向大厂冲锋!

一.日期类的实现

为了加深我们前面对类和对象的理解。我们现在来试着手搓一个日期类。

1.1声明和定义分离

我们想让.h放函数的声明。.cpp放函数的定义。

#pragma once#include<iostream>
using namespace std;
#include<assert.h>class Date
{friend istream& operator>>(istream& in, Date& d);friend ostream& operator<<(ostream& out, const Date& d);//友元声明
public:Date(int year ,int month ,int day );void Print();// Ĭinlineint GetMonthDay(int year, int month){assert(month > 0 && month < 13);static int monthDayArray[13] = { -1, 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 };if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))){return 29;}return monthDayArray[month];}int GetYear();int GetMonth();int GetDay();bool operator<(const Date& d) const;bool operator<=(const Date& d) const;bool operator>(const Date& d) const;bool operator>=(const Date& d) const;bool operator==(const Date& d) const;bool operator!=(const Date& d) const;bool CheckDate();Date operator+(int day) const;Date& operator+=(int day);Date operator++(int);//后置Date& operator++();//前置Date operator--(int);//后置Date& operator--();//前置Date& operator-=(int day);Date operator-(int day) const;int operator-(const Date& d) const;
private:int _year;int _month;int _day;
};
istream& operator>>(istream& in,  Date& d);
ostream& operator<<(ostream& out, const Date& d);

我们日期类主要实现他的比较和日期类之间的相互运算。

1.2日期类+=整数

这里我们的思路是先将整数加到天数上。然后如果天数不超过当月天数。直接返回即可。否则说明日期比当月的所有日期都大。则向下月借位。天数减去当月天数之和,以此类推知道天数不超过当月的最大天数位置。如果12借位则年份+1,月份改为1即可。

int GetMonthDay(int year, int month)
{assert(month > 0 && month < 13);static int monthDayArray[13] = { -1, 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 };if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))){return 29;}return monthDayArray[month];
}
Date& Date::operator+=(int day)
{_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month == 13){_year++;_month = 1;}}return *this;
}

1.3日期类+整数

现在我们实现日期类+整数,也就是不改变日期类。返回日期类+=整数的结果。那我们可以复用日期类+=整数的逻辑。为了不修改日期类。我们对日期类拷贝一份tmp。让tmp进行+=的逻辑这样改变就不会日期类。

Date Date::operator+(int day) const
{Date tmp=*this;tmp +=day;return tmp;
}

1.4日期类-=整数

这里思路和我们前面实现+的思路一样。都是通过借位的思想。我们向当天数-day。
然后当天数!>0时,向上一个月借位,天数+=上个月的天数(注意是上个月的,因为当月的天数已经被减过了)。如果是1月的话,借去年12月的天数。让月份=12然后年份–。

Date& Date::operator-=(int day)
{_day -= day;while (_day <= 0){if (_month == 1){_month = 12;_day += GetMonthDay(--_year, _month);}else{_day += GetMonthDay(_year, --_month);}}return *this;
}

1.5日期类-日期

日期类-日期我们就复用-=即可。

Date Date::operator-(int day) const
{Date tmp=*this;tmp -= day;return tmp;
}

1.6复用对比

在这里插入图片描述

1.7日期类==日期类

判断两个日期类很简单。我们只需要判断是否他们的年月日都相等即可。

bool Date::operator==(const Date& d) const
{if (_year == d._year && _month == d._month && _day == d._day){return true;}else{return false;}
}

1.8日期类<日期类

判断两个日期类<。
先比较年。
<返回true。
==继续比较月。月<返回true。 ==返回比较天。
剩下的情况都是false的情况。直接返回false.

bool Date::operator<(const Date& d) const
{if (_year < d._year)//比较年{return true;}else if (_year == d._year)//年相等{if (_month < d._month)//判断月{return true;}else if (_month == d._month)//月相等{return _day < d._day; //判断天}}return false;//年不相等
}

1.9比较复用

剩下的我们通过前面实现的<和==复用即可。

bool Date::operator!=(const Date& d) const
{return !(*this == d);
}
bool Date::operator<=(const Date& d) const
{return *this < d || *this == d;
}
bool Date::operator>(const Date& d) const
{return !(*this < d)&&!(*this==d);
}
bool Date::operator>=(const Date& d) const
{return !(*this < d);
}

1.10前置和后置

前置我们拷贝一份*this,在复用+=或-=即可。

Date Date::operator++(int)
{Date tmp = *this;*this += 1;return tmp;
}
Date& Date::operator++()
{*this += 1;return *this;
}
Date Date::operator--(int)
{Date tmp=*this;*this-= 1;return tmp;
}
Date& Date::operator--()
{*this -= 1;return *this;
}

1.11日期类-日期类

两个日期类相减得出他们之间相差的天数。
我们的思路就是直接让小的天数一直相加,直到相加到小的日期和大的日期相等即可。每次日期++就用一个变量记录天数即可。

int Date::operator-(const Date& d) const
{int sum = 0;int flag = 1;Date max, min;max = *this;min = d;if (*this < d)//假设法{swap(max, min);flag = -1;}while (min!=max){sum++; min++;}sum *=flag;return sum;
}

1.12日期类IO

因为类的成员函数默认*this抢占了第一个位置。和我们平时的写法不一样。所以我们把日期类的输出和输出放在类外面。那放在类外面我们如何访问类的成员变量呢?那我们就可以加一个友元函数声明。

istream& operator>>(istream& in, Date& d)
{cout<<"请依次输入年月日:"<<endl;in >>d._year>> d._month >> d._day;return in;
}
ostream& operator<<(ostream& out, const Date& d)
{out << d._year <<"年" << d._month<<"月" << d._day<<"日";return out;
}

为了实现连续输入或输出。我们需要返回istrem或ostrem对象。

同时注意流对象不支持拷贝。所以istrem或ostrem必须用引用。

二.取地址运算符重载

2.1const成员函数

  • 定义
    将const修饰的成员函数称之为const成员函数,const修饰成员函数放到成员函数参数列表的后面。

  • const修饰
    const实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。const 修饰Date类的Print成员函数,Print隐含的this指针由 Date* const this 变为const Date* const this。

    不写加const。

加上const。

同时非const成员也可以调用const成员函数。因为权限可以缩小。所以加上const可以防止我们的程序不小心篡改(原本不应该修改却不小心修改会报错),同时也让我们的的成员函数传参更宽泛,const成员也可以调用。所以能加尽加。

2.2取地址运算符重载

取地址运算符重载分为普通取地址运算符重载和const取地址运算符重载,⼀般这两个函数编译器自动生成的就可以够我们⽤了,不需要去显示实现。除非⼀些很特殊的场景,比如我们不想让别⼈取到当前类对象的地址,就可以自己实现⼀份,胡乱返回⼀个地址。

class Date
{
public:Date* operator&(){return this;// return nullptr;}const Date* operator&()const{return this;// return nullptr;}
private:int _year; // 年int _month; // ⽉int _day; // ⽇
};

一般这两个成员函数都不需要我们显示的写。因为他们两个是默认成员函数。

按理说我们只写const成员函数即可。因为不论是const成员还是非const成员都可以调用。但是const成员调用返回的是const this*。所以还需要写两份。并且编译器调用时会调用最匹配的。

三.再探构造函数

  • 初始化列表
    之前我们实现构造函数时,初始化成员变量主要使用函数体内赋值,构造函数初始化还有⼀种方式,就是初始化列表,初始化列表的使用方式是以⼀个冒号开始,接着是⼀个以逗号分隔的数据成员列表,每个"成员变量"后面跟⼀个放在括号中的初始值或表达式。

大概形式如下:

 Date(int& x, int year = 1, int month = 1, int day = 1):_year(year),_month(month),_day(day),_t(12),_ref(x),_n(1){// error C2512: “Time”: 没有合适的默认构造函数可⽤
// error C2530 : “Date::_ref” : 必须初始化引⽤
// error C2789 : “Date::_n” : 必须初始化常量限定类型的对象 
}
  • 定义的位置
    每个成员变量在初始化列表中只能出现⼀次,语法理解上初始化列表可以认为是每个成员变量定义初始化的地方。因为初始化列表是定义的地方所以,只能初始化一次。否则就会变成多次定义。

  • 定义初始化
    引用成员变量,const成员变量,没有默认构造的类类型变量,必须放在初始化列表位置进行初始化,否则会编译报错。

class Time
{
public:Time(int hour=0):_hour(hour){cout << "Time()" << endl;}
private:int _hour;
};
class Date
{
public:Date(int& x,int year = 1, int month = 1, int day = 1):_year(year), _month(month), _day(day),a(1),_ref(x)//成员定义{// error C2512: “Time”: 没有合适的默认构造函数可⽤// error C2530 : “Date::_ref” : 必须初始化引⽤// error C2789 : “Date::_n” : 必须初始化常量限定类型的对象}void Print() const{cout << _year << "-" << _month << "-" << _day << endl;}
private://声明int _year;int _month;int _day; int main();int& _ref;const int a;Time _t;
};

引用成员变量,const成员变量必须在初始化列表初始化。因为他们必须在定义的地方初始化。

没有默认构造的类类型也必须在初始化列表初始化,因为他必须手动传参调用构造函数。
那初始化列表和函数体内赋值可以混着用吗?
可以,因为有些场景必须混着用。

Date(int& x,int year = 1, int month = 1, int day = 1):_year(year), _month(month), _day(day),a(1),_ref(x),_ptr((int*)malloc(size(int)//成员定义
{if (_ptr == nullptr){perror(malloc fail!);}
}

例如有个指针,我们malloc以后需要检查是否失败。那就必须在函数体内检查。

  • 缺省值
    C++11支持在成员变量声明的位置给缺省值,这个缺省值主要是给没有显示在初始化列表初始化的成员使用的。
private://声明int _year=1;int _month=1;int _day=1; int* _ptr=((int*)malloc(sizeof(int)));

在声明的位置给一个缺省值。
在这里插入图片描述

  • 总结
    尽量使用初始化列表初始化,因为那些你不在初始化列表初始化的成员也会走初始化列表,如果这个成员在声明位置给了缺省值,初始化列表会用这个缺省值初始化。如果你没有给缺省值,对于没有显⽰在初始化列表初始化的内置类型成员是否初始化取决于编译器,C++并没有规定。对于没有显示在初始化列表初始化的⾃定义类型成员会调⽤这个成员类型的默认构造函数,如果没有默认构造会编译错误。
    所以初始化列表能写尽写,因为就算你不写他也会走初始化列表。

  • 初始化顺序
    初始化列表中按照成员变量在类中声明顺序进行初始化,跟成员在初始化列表出现的的先后顺序无关。建议声明顺序和初始化列表顺序保持⼀致。

大家看一下这道题选什么。

可能很多同学都会觉得选A。但实际不是这样的。因为初始化列表初始化的顺序是声明的顺序。

声明是顺序是他们在内存存放的顺序。初始化是按照内存中的顺序初始化。

四.类型转换

class A
{
public://构造函数explicit就不再⽀持隐式类型转换// explicit A(int a1)A(int a1):_a1(a1){}//explicit A(int a1, int a2)A(int a1, int a2):_a1(a1), _a2(a2){}void Print(){cout << _a1 << " " << _a2 << endl;}
private:int _a1 = 1;int _a2 = 2;
};
int main()
{// 1构造⼀个A的临时对象,再⽤这个临时对象拷⻉构造aa3//编译器遇到连续构造+拷⻉构造->优化为直接构造A aa1 = 1;aa1.Print();const A& aa2 = 1;// C++11之后才⽀持多参数转化A aa3 = { 2,2 };return 0;
}
  • 隐式类型转化
    C++支持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数。

    这里我们可以验证一下。

这里报错是为啥?
因为隐式类型转化生成是临时对象,临时对象具有常性。所以要加上const引用。

那隐式类型转化有什么用?

class Stack
{
public:void Push(const A& aa){}
private:int top;
};
int main()
{Stack s;A aa = 1;s.Push(aa);s.Push(1);return 0;
}


可以发现隐式类型转化可以让我们写代码更加方便简洁。

  • explicit
    如果不想发生隐式类型转化, 构造函数前面加explicit就不再支持隐式类型转换。

五.static成员

  • 静态成员变量
    用static修饰的成员变量,称之为静态成员变量,静态成员变量⼀定要在类外进行初始化。
  • 共享
    静态成员变量为所有类对象所共享,不属于某个具体的对象,不存在对象中,存放在静态区。

  • 静态成员函数
    用static修饰的成员函数,称之为静态成员函数,静态成员函数没有this指针。

  • 访问权限
    静态成员函数中可以访问其他的静态成员,但是不能访问非静态的,因为没有this指针。非静态的成员函数,可以访问任意的静态成员变量和静态成员函数。

  • 指定类域
    突破类域就可以访问静态成员,可以通过类名::静态成员或者对象.静态成员来访问静态成员变量和静态成员函数。

  • 访问限定符
    静态成员也是类的成员,受public、protected、private访问限定符的限制。

  • 缺省值
    静态成员变量不能在声明位置给缺省值初始化,因为缺省值是个构造函数初始化列表的,静态成员变量不属于某个对象,不走构造函数初始化列表。

  • 练习一
    题目:求1+2+3…+n

这道题目把常规的方法都限制了。但是这道题可以用我们的静态成员解决。
这道题主要修饰构造出循环这个条件。所以我们可以用一个类数组来构造这个条件。
定义一个n大小的类数组。那就会调用n次构造。我们只需要定义两个静态成员。然后每次构造把当前的值累加即可。

class Sum {public:Sum() {_ret += _i;++_i;}static int GetRet() {return _ret;}private:static int _i;static int _ret;
};
int Sum::_i = 1;
int Sum::_ret = 0;
class Solution {public:int Sum_Solution(int n) {//变⻓数组Sum arr[n];return Sum::GetRet();}
};

  • 练习二
C c;
int main()
{A a;B b;static D d;return 0;
}


六.友元

  • 定义
    友元提供了⼀种突破类访问限定符封装的方式,友元分为:友元函数和友元类,在函数声明或者类声明的前面加friend,并且把友元声明放到⼀个类的里面。
class A
{// 友元声明friend void func(const A& aa, const B& bb);
private:int _a1 = 1;int _a2 = 2;
};
void func(const A& aa, const B& bb){cout << aa._a1 << endl;cout << bb._b1 << endl;}

例如这里func是A的好朋友,func就可以访问A的成员。

  • 声明
    外部友元函数可访问类的私有和保护成员,友元函数仅仅是⼀种声明,他不是类的成员函数。

  • 声明位置
    友元函数可以在类定义的任何地方声明,不受类访问限定符限制。

  • 多个友元
    ⼀个函数可以是多个类的友元函数。

class A
{// 友元声明friend void func(const A& aa, const B& bb);
private:int _a1 = 1;int _a2 = 2;
};
class B
{// 友元声明friend void func(const A& aa, const B& bb);
private:int _b1 = 3;int _b2 = 4;
};

func既是A的友元又是B的友元。

  • 友元类
    友元类中的成员函数都可以是另⼀个类的友元函数,都可以访问另⼀个类中的私有和保护成员
class A
{// 友元声明friend class B;
private:int _a1 = 1;int _a2 = 2;
};
class B
{
public:void func1(const A& aa){cout << aa._a1 << endl;cout << _b1 << endl;}void func2(const A& aa){cout << aa._a2 << endl;cout << _b2 << endl;}
private:int _b1 = 3;int _b2 = 4;
};
int main()
{A aa;B bb;bb.func1(aa);bb.func1(aa);return 0;
}

B是A的友元类。B的所有成员函数都可以访问A的成员变量。

  • 单向性
    友元类的关系是单向的,不具有交换性,比如A类是B类的友元,但是B类不是A类的友元。

  • 传递性
    友元类关系不能传递,如果A是B的友元,B是C的友元,但是A不是C的友元。

  • 使用
    有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

七.内部类

  • 定义
    如果⼀个类定义在另⼀个类的内部,这个内部类就叫做内部类。内部类是⼀个独立的类,跟定义在全局相比,他只是受外部类类域限制和访问限定符限制,所以外部类定义的对象中不包含内部类。
class A
{
private:static int _k;int _h = 1;
public:class B // B默认就是A的友元{public:void foo(const A& a){cout << _k << endl; //OKcout << a._h << endl; //OK}private:int _b;};
};
int A::_k = 1;
int main()
{cout << sizeof(A) << endl;A::B b;A aa;b.foo(aa);
}


所以刚刚OJ的代码也可以改成内部类

class Solution {// 内部类class Sum{public:Sum(){_ret += _i;++_i;}};static int _i;static int _ret;public:int Sum_Solution(int n) {// 变⻓数组Sum arr[n];return _ret;}
  • 默认友元
    内部类默认是外部类的友元类。
  • 封装
    内部类本质也是⼀种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使用,那么可以考虑把A类设计为B的内部类,如果放到private/protected位置,那么A类就是B类的专属内部类,其他地方都用不了。

八.匿名对象

  • 定义
    用类型(实参)定义出来的对象叫做匿名对象,相比之前我们定义的类型对象名(实参)定义出来的叫有名对象。

匿名对象让我们写代码更方便。

  • 生命周期
    匿名对象的生命周期只在当前⼀行,⼀般临时定义⼀个对象当前用⼀下即可,就可以定义匿名对象。

    可以看到未打印1之前,A就析构了。因为匿名对象声明周期只在当前行。

后言

这就是类和对象的深入理解。今天讲了很多内容。大家自己好好消化。感谢各位的耐心垂阅!咱们下期见!拜拜~

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

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

相关文章

Linux中安装maven

Linux中安装maven 1.下载2.安装3.配置环境变量4.maven相关配置 1.下载 下载地址&#xff1a;https://maven.apache.org/download.cgi 2.安装 指定位置上传压缩包&#xff1a; 解压&#xff1a; tar -zxvf apache-maven-3.9.5-bin.tar.gz修改解压缩后的文件名: mv apac…

Netty笔记09-网络协议设计与解析

文章目录 前言一、协议设计1. 数据格式2. 消息长度3. 编码方式4. 错误处理5. 安全性 二、协议解析1. 消息分隔2. 粘包与半包处理3. 校验机制 三、为什么需要协议&#xff1f;四、redis 协议五、HTTP 协议六、自定义协议要素编解码器&#x1f4a1; 什么时候可以加 Sharable 前言…

【论文阅读】Act3D: 3D Feature Field Transformers for Multi-Task Robotic Manipulation

Abstract 3d感知表示非常适合机器人操作&#xff0c;因为它们很容易编码遮挡并简化空间推理。许多操作任务在末端执行器姿态预测中需要较高的空间精度&#xff0c;这通常需要高分辨率的3d特征网格&#xff0c;这对于处理来说计算成本很高。因此&#xff0c;大多数操作policies…

基于密码的大模型安全治理的思考

文章目录 前言一、大模型发展现状1.1 大模型技术的发展历程1.2 大模型技术的产业发展二、大模型安全政策与标准现状2.1 国外大模型安全政策与标准2.2 我国大模型安全政策与标准前言 随着大模型技术的迅速发展和广泛应用,其安全性问题日益凸显。密码学作为网络空间安全的核心技…

Unity webgl跨域问题 unity使用nginx设置跨域 ,修改请求头

跨域 什么是跨域 跨域是指浏览器因安全策略限制&#xff0c;阻止一个域下的网页访问另一个域下的资源。 一些常见的跨域情况&#xff1a; 协议不同 从 http://example.com 请求 https://example.com。域名不同 从 http://example.com 请求 http://anotherdomain.com。端口不…

《锐捷AP 胖模式配置示例》

目录 WEB配置方式: 1. 登录 AP 管理界面 2. 配置无线服务 3. 配置射频参数 4. 配置 VLAN (如果需要) 5. 配置 IP 地址 6. 其他高级设置(根据需求) 命令行配置: 1. 进入特权模式 2. 进入全局配置模式 3. 配置管理 IP 地址 4. 创建无线 SSID 5. 配置 SSID 加密…

多线程下的共享变量访问数据竞争的问题

多线程下对共享变量的写存在数据竞问题可导致数据与预期不一致。最近在研究race conditions漏洞&#xff0c;用以下python 代码记录一下&#xff0c;以此论证&#xff0c;如下&#xff1a; from concurrent.futures import ThreadPoolExecutor globalNum 5 def test():global…

【深度分析】OpenAI o1是最强的推理模型,却不是最强模型!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;专注于分享AI全维度知识&#xff0c;包括但不限于AI科普&#xff0c;AI工…

一般在写SQL时需要注意哪些问题,可以提高查询的效率?

很多人写SQL按照自己喜好&#xff0c;没有规则意识&#xff0c;这对于自主查询影响不大&#xff0c;你爱怎么搞就怎么搞&#xff0c;一旦涉及到提交任务或团队共享&#xff0c;就不能乱写了&#xff0c;会浪费资源影响到开发效率&#xff0c;严重的甚至会服务器瘫痪。 提几个关…

python-在PyCharm中使用PyQt5

文章目录 1. 安装 PyQt5 和QtTools2. QtDesigner 和 PyUIC 的环境配置2.1 在 PyCharm 添加 Create Tools2.2 添加 PyUIC 工具 3. 创建ui界面4. 使用python调用ui界面参考文献 1. 安装 PyQt5 和QtTools QT 是最强大的 GUI 库之一&#xff0c;PyQt5 是 Python 绑定 QT5 应用的框…

idea一个窗口打开多个仓库的代码

一、背景 最近新进了一家外包公司&#xff0c;这个项目由于是微服务的&#xff0c;且每个微服务都独立用一个仓库进行代码管理。看项目的时候&#xff0c;我们不能一个窗口&#xff0c;只打开一个仓库代码&#xff0c;那样看起来会非常麻烦&#xff0c;一开始对项目全貌的了解…

Get包中的根组件

文章目录 1. 知识回顾2. 使用方法2.1 源码分析2.2 常用属性 3. 示例代码4. 内容总结 我们在上一章回中介绍了"Get包简介"相关的内容&#xff0c;本章回中将介绍GetMaterialApp组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 知识回顾 我们在上一章回中已经…

多线程篇(Fork/Join)(持续更新迭代)

目录 知识大纲 一、简介 二、工作窃取算法 三、设计思想 步骤一&#xff1a;分割任务 步骤二&#xff1a;执行任务并合并结果 四、使用 五、异常处理 六、Fork/Join框架的实现原理 1. ForkJoinTask的fork方法实现原理 2. ForkJoinTask的join方法实现原理 七、源码剖…

Java-数据结构-二叉树-习题(三)  ̄へ ̄

文本目录&#xff1a; ❄️一、习题一(前序遍历非递归)&#xff1a; ▶ 思路&#xff1a; ▶ 代码&#xff1a; ❄️二、习题二(中序遍历非递归)&#xff1a; ▶ 思路&#xff1a; ▶ 代码&#xff1a; ❄️三、习题三(后序遍历非递归)&#xff1a; ▶ 思路&#xff1a; …

数据结构(7.3_3)——平衡二叉树的删除

平衡二叉树的删除 删除结点后&#xff0c;要保持二叉排序树的特性不变(左<中<右) 若删除结点导致不平衡&#xff0c;则需要调整平衡 平衡二叉树的删除步骤 删除结点(方法同"二叉排序树")一路向北找到最小不平衡子树&#xff0c;若没有找到&#xff0c;则不需…

【秋招笔试-支持在线评测】8.28华为秋招(已改编)-三语言题解

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 大厂实习经历 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 华为专栏传送🚪 -> 🧷华为春秋招笔试 目前今年秋招的笔…

01Frenet与Cardesian坐标系(基础知识)

1 简介 Frenet坐标系是一种在几何学和物理学中常用的坐标系&#xff0c;特别是在轨迹规划和机器人控制中。它由法国数学家Jean Frenet于1847年为了解决在求解某些几何问题时遇到的环形坐标系的问题而提出的。它依据曲线的切线和法线来定义坐标轴&#xff0c;主要用于局部地描述…

104.WEB渗透测试-信息收集-FOFA语法(4)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;103.WEB渗透测试-信息收集-FOFA语法&#xff08;3&#xff09; 打开fofa搜索引擎 搜索输…

YOLOv9改进策略【卷积层】| GnConv:一种通过门控卷积和递归设计来实现高效、可扩展、平移等变的高阶空间交互操作

一、本文介绍 本文记录的是利用GnConv优化YOLOv9的目标检测方法研究。YOLOv9在进行目标检测时&#xff0c;需要对不同层次的特征进行融合。GnConv可以考虑更高阶的空间交互&#xff0c;能够更好地捕捉特征之间的复杂关系&#xff0c;从而增强特征融合的效果&#xff0c;提高模…

2024/9/17 pytorch-卷积神经网络

一、torch.nn pytorch有很多接口&#xff0c;其中的torch.nn可以让我们方便的调用以便生成神经网络各层 1.torch.nn.Module 是一个构成神经网络层的一个基本类别&#xff0c;一般生成一个类别来继承nn.module torch.tensor(a)将a初始化为一个tensor类型数据 一般这种已经固…