Cpp类和对象(中续)(5)
文章目录
- 前言
- 一、赋值运算符重载
- 运算符重载
- 赋值运算符重载
- 赋值运算符不可重载为全局函数
- 前置++和后置++的重载
- 二、const修饰成员函数
- 三、取地址及const取地址操作符重载
- 四、日期类的实现
- 构造函数
- 日期 += 天数
- 日期 + 天数
- 日期 -= 天数
- 日期 - 天数
- 日期类的大小比较
- 日期类 > 日期类
- 日期类 == 日期类
- 日期类 >= 日期类
- 日期类 < 日期类
- 日期类 <= 日期类
- 日期类 != 日期类
- 日期类 - 日期类
- 五、流插入流提取运算符重载
- 总结
前言
继承上节的内容,本节内容依旧量大管饱!!
一、赋值运算符重载
运算符重载
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,其目的就是让自定义类型可以像内置类型一样可以直接使用运算符进行操作。
请记住这个目的!我们的接下来的一切都是围绕这个来展开
运算符重载函数也具有自己的返回值类型,函数名字以及参数列表。其返回值类型和参数列表与普通函数类似。
运算符重载函数名为:关键字operator后面接需要重载的操作符符号。
注意:
- 不能通过连接其他符号来创建新的操作符:比如operator@。(需要是C/C++语法中存在)
- 重载操作符必须有一个类类型或枚举类型的操作数。(不能去重载运算符改变内置类型的行为) -> 其实要真那么搞也可以,但是很无聊,没什么实用的
- 用于内置类型的操作符,重载后其含义不能改变。-> 例如内置的整型+,不能改变其含义
- 作为类成员的重载函数时,函数有一个默认的形参this,限定为第一个形参。
- sizeof 、:: 、.* 、?: 、. 这5个运算符不能重载。
- 并不是运算符都是需要重载的,需要看是否有存在的意义,参数部分需要对应顺序
// 来个实际例子
class Date
{
public:Date(int year = 0, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}// 注意此时该函数的第一个形参默认为this指针bool operator==(const Date& d)// 运算符重载函数{return _year == d._year&&_month == d._month&&_day == d._day;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2024, 9, 22);Date d2 = d1;// 注意优先级cout << (d1 == d2) << endl; // 1cout << d1.operator==(d2) << endl; // 与上一条语句等价return 0;
}
显然第一种 d1 == d2 这种形式相当明了,就好像Date真的是我们的内置类型一样,其实说白了,还是编译器帮我们化成了第二种形式,不信我们可以看下汇编形式:

还是那句话,当你觉得轻松的时候,总是有人为你负重前行
赋值运算符重载
先上代码:
class Date
{
public:Date(int year = 0, int month = 1, int day = 1) // 构造函数{_year = year;_month = month;_day = day;}Date& operator=(const Date& d) // 赋值运算符重载函数{if (this != &d) // 防止会有 d1 = d1 这样自己赋值给自己{_year = d._year;_month = d._month;_day = d._day;}return *this;}void Print()// 打印函数{cout << _year << "年" << _month << "月" << _day << "日" << endl;}
private:int _year;int _month;int _day;
};
我们要注意以下几点:
- 参数类型设置为引用,并用const进行修饰 -> 由于是自定义类型传参,我们若是使用传值传参,会额外调用一次拷贝构造函数,所以函数的第二个参数最好使用引用传参(第一个参数是默认的this指针,我们管不了)。并且我们也不改变它,那就用 const 来修饰
- 函数的返回值使用引用返回 -> 本质上是为了支持连续赋值,所以必须要有个返回值,而且很显然是返回左操作数 d3 = d2 = d1; 所以我们在这里返回 this 指针,且因为此时出了函数作用域this指针指向的对象并没有被销毁,所以可以使用引用返回,又省了拷贝多余的资源消耗
- 一个类如果没有显示定义赋值运算符重载,编译器也会自动生成一个,完成对象按字节序的值拷贝 -> 没错,赋值运算符重载编译器也可以自动生成,并且也是支持连续赋值的。但是编译器自动生成的赋值运算符重载完成的是对象按字节序的值拷贝,例如d2 = d1,编译器会将d1所占内存空间的值完完全全地拷贝到d2的内存空间中去,类似于memcpy
// 请注意区分
Date d1(2024,9,22);
Date d2 = d1; // 拷贝构造
Date d3;
d3 = d1; // 赋值// 拷贝构造函数:用一个已经存在的对象去构造初始化另一个即将创建的对象
// 赋值运算符重载函数:在两个对象都已经存在的情况下,将一个对象赋值给另一个对象
赋值运算符不可重载为全局函数
赋值运算符重载跟拷贝构造类似,如果不显式实现,编译器会生成一个默认的赋值运算符重载,此时用户再类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突,故而赋值运算符只能是类的成员函数(其他运算符函数可以重载为全局函数)
《C++ Primer》第5版P500有言:
默认生成赋值运算符重载对于内置类型与自定义类型处理方式:
- 内置类型成员变量直接赋值的
- 自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值
同样的,我们有个深拷贝和浅拷贝的问题,方式还是跟拷贝构造方式一样,当涉及到动态资源申请的时候深拷贝,否则浅拷贝即可
前置++和后置++的重载
这两个妙就妙在一样就只有一个操作符,一个操作符在前一个在后
C++给出了它的解决方案:
//++d1
Date& operator++()
{_day += 1;return *this;
}//d1++
Date operator++(int)
{Date temp(*this);_day += 1;return temp;
}
请注意,后置++重载函数中的参数int没有实际作用,只是为了与前置++构成函数重载,以便区分
二、const修饰成员函数
将const修饰的 “成员函数” 称之为 const 成员函数,const修饰类成员函数,实际修饰改成员隐含的 this 指针,表明在该成员函数中不能对类的任何成员进行修改,如图:

在讲解具体的实用场景前,我们还可以先来看看这四个问题,答案和解释我都会相应给出:
- const对象可以调用非const成员函数吗?
- 非const对象可以调用const成员函数吗?
- const成员函数内可以调用其他的非const成员函数吗?
- 非const成员函数内可以调用其他的const成员函数吗
答案是:不可以、可以、不可以、可以
解释:
5. 非const成员函数,即成员函数的this指针没有被const所修饰,我们传入一个被const修饰的对象,用没有被const修饰的this指针进行接收,属于权限的放大,函数调用失败
6. const成员函数,即成员函数的this指针被const所修饰,我们传入一个没有被const修饰的对象,用被const修饰的this指针进行接收,属于权限的缩小,函数调用成功
7. 在一个被const所修饰的成员函数中调用其他没有被const所修饰的成员函数,也就是将一个被const修饰的this指针的值赋值给一个没有被const修饰的this指针,属于权限的放大,函数调用失败
8. 在一个没有被const所修饰的成员函数中调用其他被const所修饰的成员函数,也就是将一个没有被const修饰的this指针的值赋值给一个被const修饰的this指针,属于权限的缩小,函数调用成功
权限可以平移,也可以缩小,但是不可以放大
好,我们接下来来看以下代码:
// Print()成员函数没有被const修饰
int main()
{Date d1(2024, 9, 22);d1.Print(); // right,权限平移const Date d2(2024, 9, 22);d2.Print(); // err,权限放大return 0;
}
但是并非所有函数都需要加上 const 修饰的!如果对成员变量进行读写访问的函数,不能加上 const ,另外,const修饰成员函数是修饰this指针的,那么 流插入>> 与 流提取<< 不是在类中实现,没有隐含的this指针,不能使用 const 修饰
三、取地址及const取地址操作符重载
这两个默认成员函数一般不用重新定义,编译器会默认生成的,无需你多虑
class Date
{
public:Date* operator&(){return this;}const Date* operator&() const{return this;}
private:int _year; int _month; int _day;
};
四、日期类的实现
学完了这6个默认成员函数,我们来写个日期类巩固一下吧:
class Date
{
public:// 构造函数Date(int year = 1900, int month = 1, int day = 1);// 打印函数void Print() const;// 日期+=天数Date& operator+=(int day);// 日期+天数Date operator+(int day) const;// 日期-=天数Date& operator-=(int day);// 日期-天数Date operator-(int day) const;// 前置++Date& operator++();// 后置++Date operator++(int);// 前置--Date& operator--();// 后置--Date operator--(int);// 日期的大小关系比较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;// 日期-日期int operator-(const Date& d) const;// 析构,拷贝构造,赋值重载可以不写,使用默认生成的即可private:int _year;int _month;int _day;
};
构造函数
// 获取某年某月的天数
inline int GetMonthDay(int year, int month)
{// 数组存储平年每个月的天数static int dayArray[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };int day = dayArray[month];if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))){//闰年2月的天数day = 29;}return day;
}
// 构造函数
Date::Date(int year, int month, int day)
{// 检查日期的合法性if (year >= 0&& month >= 1 && month <= 12&& day >= 1 && day <= GetMonthDay(year, month)){_year = year;_month = month;_day = day;}else{// 严格来说抛异常更好cout << "非法日期" << endl;cout << year << "年" << month << "月" << day << "日" << endl;}
}
其中,我们注意一下这个GetMonthDay函数:
- 该函数可能被多次调用,所以我们最好将其设置为内联函数
- 函数中存储每月天数的数组最好是用static修饰,存储在静态区,避免每次调用该函数都需要重新开辟数组
- 逻辑与应该先判断 month == 2 是否为真,因为当不是2月的时候我们不必判断是不是闰年,短路判断
日期 += 天数
因为出了作用域对象还存在,于是我们用引用返回
逻辑如下:
1.若日已满,则日减去当前月的天数,月加一。
2.若月已满,则将年加一,月置为1
// 日期 += 天数
Date& Date::operator+=(int day)
{if (day<0){// 复用operator-=*this -= -day;}else{_day += day;// 日期不合法,通过不断调整,直到最后日期合法为止while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month > 12){_year++;_month = 1;}}}return *this;
}
日期 + 天数
因为返回对象的值不变,但我们要返回变化后的值,于是就可以通过复用+=、创建临时变量tmp来解决,因为tmp出了作用域就销毁,于是我们用传值返回
// 日期 + 天数
Date Date::operator+(int day) const
{Date tmp(*this);// 拷贝构造tmp,用于返回// 复用operator+=tmp += day;return tmp;
}
日期 -= 天数
逻辑如下:
1.若日为负数,则月减一。
2.若月为0,则年减一,月置为12。
3.日加上当前月的天数
// 日期 -= 天数
Date& Date::operator-=(int day)
{if (day < 0){// 复用operator+=*this += -day;}else{_day -= day;// 日期不合法,通过不断调整,直到最后日期合法为止while (_day <= 0){_month--;if (_month == 0){_year--;_month = 12;}_day += GetMonthDay(_year, _month);}}return *this;
}
日期 - 天数
跟日期 + 天数类似,也是复用
// 日期-天数
Date Date::operator-(int day) const
{Date tmp(*this);// 拷贝构造tmp,用于返回// 复用operator-=tmp -= day;return tmp;
}
日期类的大小比较
这里,我们将充分发挥复用的智慧!
日期类 > 日期类
逻辑:年大则大,月大则大,年月相等比日
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;
}
日期类 == 日期类
逻辑:年月日均相等即为真
bool Date::operator==(const Date& d) const
{return _year == d._year&&_month == d._month&&_day == d._day;
}
日期类 >= 日期类
逻辑:复用前面两个
bool Date::operator>=(const Date& d) const
{return *this > d || *this == d;
}
日期类 < 日期类
逻辑:>= 的反面就是 <
bool Date::operator<(const Date& d) const
{return !(*this >= d);
}
日期类 <= 日期类
逻辑:> 的反面就是 <=
bool Date::operator<=(const Date& d) const
{return !(*this > d);
}
日期类 != 日期类
逻辑:== 的反面就是 !=
bool Date::operator!=(const Date& d) const
{return !(*this == d);
}
日期类 - 日期类
其实也就是算两个日期之差,它还是有点意义的
试想一下,假如你未来结婚,结婚到一半,新娘子问你我们几年几月几日遇见的?
你早有准备,一下就回答上来
突然,新娘子还不死心,问你遇见当天离今天一共经历多少天?
你就可以说:“不急,我先跑个程序”
这就是日期类 - 日期类的一个实际场景运用
有两种思路,请听我细细道来:
方法一:所谓日期 - 日期,即计算传入的两个日期相差的天数。我们只需要让较小的日期的天数一直加一,直到最后和较大的日期相等即可,这个过程中较小日期所加的总天数便是这两个日期之间差值的绝对值。若是第一个日期大于第二个日期,则返回这个差值的正值,若第一个日期小于第二个日期,则返回这个差值的负值,这很容易,设置一个判别变量 flag 即可
// 日期-日期
int Date::operator-(const Date& d) const
{Date max = *this;// 假设第一个日期较大Date min = d;// 假设第二个日期较小int flag = 1;// 此时结果应该为正值if (*this < d){// 假设错误,更正max = d;min = *this;flag = -1;// 此时结果应该为负值}int n = 0;// 记录所加的总天数while (min != max){min++;// 较小的日期++n++;// 总天数++}return n*flag;
}
方法二:所谓“年、月、日”,不过也是一种进位的方式,那我们可以全把数堆给“日”这个位,先将年等同,再将月等同,最后直接将两个日期的“日”位相减即可,只需要注意返回的是正值还是负值
int Date::operator-(const Date& d)
{Date greD = (*this) > d ? *this : d;Date smlD = (*this) < d ? *this : d;while (greD._year > smlD._year) {if (isLeapYear(greD._year - 1)) greD._day += 366;else greD._day += 365;greD._year -= 1;}while (greD._month > smlD._month) {greD._month -= 1;greD._day += GetMonthDay(greD._year, greD._month);}while (greD._month < smlD._month) {greD._month += 1;greD._day -= GetMonthDay(greD._year, greD._month);}int ret = greD._day - smlD._day;return *this > d ? ret : -ret;
}
五、流插入流提取运算符重载
这个比较困难,有一些不懂的概念可以暂且放一下
其实,我们平时说cout、cin能自动识别类型,本质上就是因为重载,cout属于ostream类,cin属于istream类

假如我们 重载运算符<< 为成员函数,隐含的 this 指针占用第一个参数的位置,Date必须是左操作数,使用时候d1<<cout 是不符合我们的习惯的
于是,我们要将其重载为全局函数,并且把ostream& out放在第一个位置!但是又引出了另一个问题:类外不能访问类中的私有成员,如果将私有权限放开,就缺乏安全性,对此C++中有友元,接下来我们会涉及到,这里就使用下,虽然这个全局函数不在类中,但是可以访问私有成员函数
//友元,告诉该类这两个全局函数是我们的朋友,允许使用私有成员(在类中)friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "" << d._month << "" << d._day << "" << endl;return out;
}istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}
总结
哈哈,这个中篇终于结束了,想不到吧,学Cpp的第一个大内容就如此困难!
还有个下篇呢,继续加油吧!
相关文章:
Cpp类和对象(中续)(5)
文章目录 前言一、赋值运算符重载运算符重载赋值运算符重载赋值运算符不可重载为全局函数前置和后置的重载 二、const修饰成员函数三、取地址及const取地址操作符重载四、日期类的实现构造函数日期 天数日期 天数日期 - 天数日期 - 天数日期类的大小比较日期类 > 日期类日…...
深度学习02-pytorch-01-张量的创建
深度学习 pytorch 框架 是目前最热门的。 深度学习 pytorch 框架相当于 机器学习阶段的 numpy sklearn 它将数据封装成张量(Tensor)来进行处理,其实就是数组。也就是numpy 里面的 ndarray . pip install torch1.10.0 -i https://pypi.tuna.tsinghua.edu.cn/simp…...
pg入门9—pg中的extentions是什么
在 PostgreSQL(PG)中,Extension(扩展) 是一组预先打包的功能模块,可以轻松地添加到数据库中以扩展其功能。这些扩展通常包含新的数据类型、函数、索引方法、操作符以及其他数据库增强功能。通过扩展&#x…...
JAVA:Nginx(轻量级的Web服务器、反向代理服务器)--(1)
一、Nginx:起因 nginx为什么为开发出来,起因是什么 总述:NGINX 的开发起因源于上世纪 90 年代末至 2000 年代初的互联网快速发展。当时,互联网流量急剧增长,特别是像 Apache 这样的传统 Web 服务器在高并发连接处理方面开始显现出瓶颈。 举例子:Apache 的 "每个连接…...
互斥锁和自旋锁
1、锁: 自旋锁与互斥锁的区别主要体现在以下几个方面: 1. 实现方式 互斥锁:属于sleep-waiting类型的锁。当一个线程尝试获取已被其他线程持有的互斥锁时,该线程会被阻塞(进入睡眠状态)ÿ…...
救生圈检测系统源码分享
救生圈检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Visio…...
容器技术--Dockerfile 构建镜像
Dockerfile dockerfile 是一系列命令&参数构成的脚本,这些命令应用于基础镜像,最终创建一个新的镜像,可以提供一致的运行环境。【也可以登录容器,自己安装软件,最后commit为镜像】 命令 FROM 指定基础镜像(必须),如FROM ubuntu;每一个指令就生成一层镜像;RUN 运…...
Hive企业级调优[5]—— HQL语法优化之数据倾斜
目录 HQL语法优化之数据倾斜 数据倾斜概述 分组聚合导致的数据倾斜 优化说明 优化案例 Join导致的数据倾斜 优化说明 优化案例 HQL语法优化之数据倾斜 数据倾斜概述 数据倾斜问题通常指的是参与计算的数据分布不均,即某个key或某些key的数据量远超其他keyÿ…...
表示速度的speed与velocity语义辨析
speed 对应的中文是 速度, 比如 5KM/h, 但是语义中不带方向,所以一般用来表示标量(scalar)。velocity 对应的中文也是 速度, 比如 5KM/h, 语义中蕴含了方向, 常用于表示向量(vector)。 2024年09月22日...
Electron 图标修改
目录 1. 图片基本要求 2. 在main.js中配置icon 位置 3. 在package.json 中配置icon 位置 4. 问题:左上角图片 开发环境下显示,生产环境下不显示 1. 图片基本要求 图片格式为ico,图片像素像素为256*256; 将ico文件放在pub…...
项目扩展二:消息拉取功能的实现
项目扩展二:消息拉取功能的实现 一、回顾一下消息推送功能是如何实现的二、设计消息拉取功能1.服务器如何处理2.定义Request和Response1.定义Request2.proto文件 三、服务器实现消息拉取1.业务模块的实现:信道模块2.消费者管理模块实现O(1)获取消费者1.目…...
C语言6大常用标准库 -- 4.<math.h>
目录 引言 4. C标准库--math.h 4.1 简介 4.2 库变量 4.3 库宏 4.4 库函数 4.5 常用的数学常量 🌈你好呀!我是 程序猿 🌌 2024感谢你的陪伴与支持 ~ 🚀 欢迎一起踏上探险之旅,挖掘无限可能,共同成长&…...
【图像匹配】基于SIFT算法的图像匹配,matlab实现
博主简介:matlab图像代码项目合作(扣扣:3249726188) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于基于SIFT算法的图像匹配,用matlab实现。 一、案例背景和算法介绍 本…...
C++门迷宫
目录 开头程序程序的流程图程序游玩的效果下一篇博客要说的东西 开头 大家好,我叫这是我58。 程序 #include <iostream> using namespace std; void printmaze(const char strmaze[11][11]) {int i 0;int ia 0;for (; i < 11; i) {for (ia 0; ia <…...
用最通俗易懂的语言和例子讲解三维点云
前言: 我整体的学习顺序是看的按B站那“唯一”的三维点云的视频学习的(翻了好久几乎没有第二个...)对于深度学习部分,由于本人并没有进行学习,所以没有深究。大多数内容都进行了自己的理解并找了很多网络的资源方便理解…...
VM虚拟机下载以及激活
传统的官网已经找不到下载了,这里我将下载好的放在阿里云盘,百度云盘太慢了,懂得都得 阿里云盘分享 下载好了后会是一个exe文件,直接双击运行就可 下载无脑下一步即可,这里不做介绍 下载好了后,需要密钥这里…...
详解Ajax与axios的区别
Ajax与Axios在Web开发中都是用于发送HTTP请求的技术,但它们在多个方面存在显著的差异。以下是对两者区别的详细解析: 1. 技术原理 Ajax:Asynchronous JavaScript and XML(异步JavaScript和XML)的缩写,是一…...
golang学习笔记28——golang中实现多态与面向对象
推荐学习文档 golang应用级os框架,欢迎stargolang应用级os框架使用案例,欢迎star案例:基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识,这里有免费的golang学习笔…...
运行 xxxxApplication 时出错。命令行过长。 通过 JAR 清单或通过类路径文件缩短命令行,然后重新运行。
一、问题描述 运行 xxxxApplication 时出错。命令行过长。 通过 JAR 清单或通过类路径文件缩短命令行,然后重新运行。 二、问题分析 在idea中,运行一个springboot项目,在使用大量的库和依赖的时候,会出现报错“命令行过长”&…...
k8s自动清理pod脚本分享
检查会遇到集群节点内存消耗超过90%,我们可以筛选一些可以进行重启的pods,如脚本中涉及svc-开头的,进行触发即重启的shell编写。此项会涉及metrics组件需要安装。 #!/bin/bash# 设置内存使用率阈值为90% MEMORY_THRESHOLD90# 初始化一个数组…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...

