【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.rhkb.cn/news/425923.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5. Python之数据类型

Python数据类型有数值型&#xff0c;字符串型&#xff0c;布尔型等等 内置函数type()&#xff0c;可以查看变量的数据类型 。 一、数值类型 整数&#xff08;没有小数部分&#xff0c;包含正整数&#xff0c;负整数&#xff0c;0&#xff0c;默认为十进制数&#xff09;&…

RuoYi-Vue3使用minio图片预览不了的问题

参照官网配置好之后&#xff0c;图片预览不了 1、参照官网修改前端src\components\ImageUpload\index.vue 2、如果图片预览不了&#xff0c;发现是Minio后台返回的url地址内部包括逗号 与代码里split(",")冲突了&#xff0c; 解决方法是改成分号 多个图片可以预览了…

Pikachu靶场之csrf

CSRF 跨站请求伪造 CSRF入门及靶场实战 - FreeBuf网络安全行业门户 攻击者伪造恶意链接&#xff0c;诱使用户点击&#xff0c;这个链接附带了用户的认证凭据Cookie、Session等&#xff0c;执行操作如转账。 因为带了cookie、session&#xff0c;服务器认为是用户的行为。借用…

mysql-搭建主从复制

文章目录 1、准备主服务器2、准备从服务器3、主库配置3.1、创建MySQL主服务器配置文件&#xff1a; 4、从库配置5、搭建主从&测试5.1、使用命令行登录MySQL主服务器5.2、主机中查询master状态&#xff1a;5.3、从机中查询slave状态&#xff1a;5.4、主机中创建slave用户&am…

go-map系统学习

map底层结构 Goland的map的底层结构使用hash实现&#xff0c;一个hash表里有多个hash表节点&#xff0c;即bucket&#xff0c;每个bucket保存了map中的一个或者一组键值对。 map结构定义&#xff1a; runtime/map.go:hmap type hmap struct {// Note: the format of the hma…

从零开学C++:多态

引言&#xff1a;在我们去购买汽车票的时候&#xff0c;我们总会遇到成人全价&#xff0c;学生打折的情况。不同的对象&#xff08;成人、学生&#xff09;进行同一操作&#xff08;购买车票&#xff09;&#xff0c;得到不同的结果&#xff08;全价、打折&#xff09;&#xf…

Redis实现发布/订阅功能(实战篇)

前言 博主在学习 Redis 实现发布订阅功能的时候&#xff0c;踩了太多的坑。 不是讲解不详细&#xff0c;看的一知半解&#xff1b;就是代码有问题&#xff0c;实际压根跑不起来&#xff01; 于是博主萌生了自己写一个最新版且全程无错的博客供各位参考。希望各位不要把我才过…

深入理解IP地址分类及子网划分详解

在互联网时代&#xff0c;IP地址是网络通信的基础。无论是访问网站、发送电子邮件&#xff0c;还是进行数据传输&#xff0c;IP地址都扮演着至关重要的角色。本文将详细解析IP地址的分类及子网划分的原理&#xff0c;帮助你更好地理解网络架构及其应用。 一、什么是IP地址 IP…

教师薪酬管理系统的设计与实现

摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;老师信息因为其管理内容繁杂&#xff0c;管理数量繁多导致手工进行处理不能满足广…

Android MediaPlayer + GLSurfaceView 播放视频

Android使用OpenGL 播放视频 概述TextureView的优缺点OpenGL的优缺点 实现复杂图形效果的场景参考 概述 在Android开发中&#xff0c;使用OpenGL ES来渲染视频是一种常见的需求&#xff0c;尤其是在需要实现自定义的视频播放界面或者视频特效时。结合MediaPlayer&#xff0c;我…

吸浮毛宠物空气净化器推荐,希喂、小米、有哈宠物空气净化器测评

养猫需谨慎&#xff0c;不然就要做猫奴一辈子啦&#xff01;上次堂妹来我家住几天&#xff0c;刚开始还担心和猫处不来&#xff0c;不敢去摸它&#xff0c;走的时候已经约好下次来看它的时间&#xff0c;笑死我了。毕竟猫咪这么可爱&#xff0c;很少有人可以抵抗它的魅力。 这不…

什么是科技与艺术相结合的异形创意圆形(饼/盘)LED显示屏

在当今数字化与创意并重的时代&#xff0c;科技与艺术的融合已成为推动社会进步与文化创新的重要力量。其中&#xff0c;晶锐创显异形创意圆形LED显示屏作为这一趋势下的杰出代表&#xff0c;不仅打破了传统显示设备的形态束缚&#xff0c;更以其独特的造型、卓越的显示效果和广…

3谐振功率放大器的实际电路设计

1原理电路 下图是谐振功率放大器的原理电路&#xff0c;如果我们照着下图搭一个电路&#xff0c;会发现它可能实现不了功率放大?这是为什么&#xff1f; 2实际电路设计 2.1要注意直流馈电线路 馈电原则(馈电供电)&#xff1a; 1&#xff09;保证直流电流分量流过直流电源&…

基于SpringBoot+Vue的校园礼服装租赁系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的…

【Java 优选算法】双指针(下)

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 有效三角形的个数 题目链接 解法 解法1:暴力枚举--->O(n^3) 解法2:利用单调性,使用双指针来解决---->O(n^2) 优化:对整个数组进行排序先固定最大数在最大数的左…

【模板代码的组织结构与模板的显式实例化和声明】模板代码的组织结构与模板的显式实例化和声明

一、模板的组织结构 之前对于模板&#xff0c;我们都是写在同一个 . c p p .cpp .cpp文件下&#xff0c;那如果我们将模板分开&#xff0c;单独开一个 . h .h .h和 . c p p .cpp .cpp来创建模板&#xff0c;会发生什么&#xff1f; 首先&#xff0c;我们创建一个 m y c l a s…

【2024.08】图模互补:知识图谱与大模型融合综述-笔记

阅读目的&#xff1a;假设已有一个知识图谱&#xff0c;如何利用图谱增强模型的问答&#xff0c;如何检索知识图谱、知识图谱与模型的文本如何相互交互、如何利用知识图谱增强模型回答的可解释性。 从综述中抽取感兴趣的论文进一步阅读。 来源&#xff1a;图模互补&#xff1…

阿里云 Quick BI使用介绍

Quick BI使用介绍 文章目录 阿里云 Quick BI使用介绍1. 创建自己的quick bi服务器2. 新建数据源3. 上传文件和 使用4. 开始分析 -选仪表盘5. 提供的图表6. 一个图表的设置使用小结 阿里云 Quick BI使用介绍 Quick BI是一款全场景数据消费式的BI平台&#xff0c;秉承全场景消费…

【梯度下降|链式法则】卷积神经网络中的参数是如何传输和更新的?

【梯度下降|链式法则】卷积神经网络中的参数是如何传输和更新的&#xff1f; 【梯度下降|链式法则】卷积神经网络中的参数是如何传输和更新的&#xff1f; 文章目录 【梯度下降|链式法则】卷积神经网络中的参数是如何传输和更新的&#xff1f;1. 什么是梯度&#xff1f;2.梯度…

华为eNSP使用详解

eNSP&#xff08;Enterprise Network Simulation Platform&#xff09;是华为提供的一款网络仿真平台&#xff0c;它允许用户在没有真实设备的情况下进行网络实验和学习网络技术。eNSP可以模拟各种网络设备&#xff0c;如交换机、路由器、防火墙等&#xff0c;并支持创建多种网…