c++ 多态性
类的多态
多态概念入门
#include <iostream>
using namespace std;/*
多态的前提: 拥有继承关系的类中有相同的函数(返回类型、函数名、形参列表)
多态解决的问题:1、派生类的对象被赋值给基类对象时2、派生类的对象初始化基类的引用时3、基类的指针指向派生类时函数调用的问题
总结:没有多态时看类型。有多态时看内存。
*/class A
{
public:A() {cout << "A" << endl;}A(const A& a) {cout << "A(const A& a)" << endl;}void fun() {cout << "A::fun()" << endl;}
};class B : public A
{
public:B() {cout << "B" << endl;}B(const B& b) {cout << "B(const B& b)" << endl;}void fun() {cout << "B::fun()" << endl;}
};int main(int argc, char *argv[])
{B b;// 1、派生类的对象可以被赋值给基类对象A a = b;a.fun();// 2、派生类的对象可以初始化基类的引用A& a1 = b;a1.fun();// 3、指向基类的指针也可以指向派生类A* a2 = new B;a2->fun(); // 调用的是A类函数,但本质确实B的空间return 0;
}
多态性
多态性:例如函数重载,同一个函数名会产生不同的结果,而虚函数是实现多态性另一个重要途径
#include <iostream>
using namespace std;class A
{private:int a;public:virtual void f(); // 这是虚函数的一个地址,而不是实际的函数,地址所指向的的才是对应的函数
};int main()
{cout << sizeof(A) << endl; // 4 + 8 = 12 内存对齐原则 最终打印 16return 0;
}
普通虚函数
#include <iostream>
using namespace std;class Manmal
{public:// 注意点一:// virtual 的三种情况(为了书写规范,基类和派生类必须都写)// 1、基类有 派生类没有 可以构成虚函数// 2、基类有 派生类有 可以构成虚函数// 3、基类没有 派生类有 不可以构成虚函数virtual void sound() { cout << "发出叫声" << endl; }
};/*
注意点二:
虚函数定义时不需要再次书写 virtual 关键字
void Manmal::sound()
{ cout << "发出叫声" << endl; }
*/class Cat : public Manmal
{public:// 注意点三:// 此时,派生类中拥有和基类相同的函数,这一行为叫做函数的复写(又称覆盖),不是重载// 函数复写的最大特点:基类的指针或引用可以忽略基类已存在的版本,直接调用派生类的版本virtual void sound() { cout << "喵喵喵" << endl; }
};class Dog : public Manmal
{public:// 注意点四:// 普通虚函数派生类可以不进行复写,当注释下方语句时,派生类进行调用则会打印基类虚函数叫声// 理解:基类的虚函数是所有派生类的共同特点,当派生类不具备自己的特点时,则会显示出共同特点virtual void sound() { cout << "汪汪汪" << endl; }
};// 可以处理一切哺乳动物发出声音这种行为
void feed(Manmal &m)
{m.sound();
}
------------------------------------------------------------------------------------------------------------------
/*
void feed(Cat &cat)
{cat.sound();
}void feed(Dog &dog)
{dog.sound();
}
*/
------------------------------------------------------------------------------------------------------------------
int main()
{Cat *cat = new Cat;Dog *dog = new Dog;feed(*cat);feed(*dog);/*// 上述代码改写 并删除 feed 函数Manmal *cat = new Cat;Manmal *dog = new Dog;cat->sound();dog->sound();*/delete cat;delete dog;return 0;
}
纯虚函数
概念:相较于普通虚函数(基类中的虚函数必须实现),纯虚函数可以不用实现基类中的虚函数(也可以实现),这个基类称之为抽象基类,但是同时要求派生类必须实现虚函数代码,否则不能定义对象仍旧为抽象基类。
#include <iostream>
using namespace std;class A // 抽象基类:专门用于派生子类,自己不能定义对象
{public:// 本质:只有实现这个函数才能定义对象,这是所有派生类产生的必须条件。如:战斗机、明航客机、直升机等都必须能飞virtual void f() = 0; // 纯虚函数定义形式
};int main()
{return 0;
}
虚函数与构造函数
构造函数不能是虚函数
虚函数意味着要被派生类的各类方法进行复写,而派生类的构造并不能通过基类。
虚函数与析构函数
结论:
若一个类不会派生新的类,则析构函数只需普通函数即可;
若一个类会派生出新的类,则析构函数必须定义为虚函数;
#include <iostream>
using namespace std;class Base
{public:virtual ~Base() { cout << "~Base()" << endl; }
};class Drived1 : public Base
{public:virtual ~Drived1() { cout << "~Drived1()" << endl; }
};class Drived2 : public Base
{public:virtual ~Drived2() { cout << "~Drived2()" << endl; }
};int main()
{// 若不将析构函数定义为虚函数,那么派生类析构时就无法调用派生类的析构函数,不能产生穿透// 析构函数相较于普通函数,虚函数复写时名字可以不同,因为一个类只有一个析构函数Base *d1 = new Drived1;Base *d2 = new Drived2;delete d1;delete d2;return 0;
}
运算符重载与友元
运算符函数
在 c++ 中,操作数包含类对象时,运算符操作就是一个函数。除了赋值运算符默认之外,其余都需要进行重载才能使用。
class A
{public:// 重载了 + 运算符const A & operator+(const A &b); // const 是为了保证和普通运算符运算方式一致,如:(a+b)=c 不应该被满足
};int main()
{A a, b;a + b; // -----> a.operator+(b)}/*
返回值类型:A &
函数名:operator+
参数列表:const A &r
*/
类成员运算符重载
#include <iostream>
using namespace std;class Time
{private:int hour;int minute;int second;public:Time(int h = 0, int m = 0, int s = 0): hour(h), minute(m), second(s){};// 加法运算符操作函数重载 (t1 + t2)const Time operator+(const Time &r);// 显示时间void show();
};const Time Time::operator+(const Time &r)
{Time tmp;tmp.second = this->second + r.second;if(tmp.second >= 60){tmp.minute++;tmp.second -= 60;}tmp.minute += this->minute + r.minute;if(tmp.minute >= 60){tmp.hour++;tmp.minute -= 60;}tmp.hour += this->hour + r.hour;tmp.hour %= 24;return tmp;
}void Time::show()
{cout << hour << ":" << minute << ":" << second << endl;
}int main()
{Time t1(1, 50, 33);Time t2(0, 20, 33);Time t3 = t1 + t2;t3.show();return 0;
}
非类成员运算符重载
#include <iostream>
using namespace std;class Time
{public:int hour;int minute;int second;public:Time(int h = 0, int m = 0, int s = 0): hour(h), minute(m), second(s){};// 加法运算符操作函数重载 (t1 + t2)const Time operator+(const Time &r);// 类内:输出运算符操作函数重载ostream &operator<<(ostream &out); // 显示时间void show();
};const Time Time::operator+(const Time &r)
{Time tmp;tmp.second = this->second + r.second;if(tmp.second >= 60){tmp.minute++;tmp.second -= 60;}tmp.minute += this->minute + r.minute;if(tmp.minute >= 60){tmp.hour++;tmp.minute -= 60;}tmp.hour += this->hour + r.hour;tmp.hour %= 24;return tmp;
}void Time::show()
{cout << hour << ":" << minute << ":" << second << endl;
}// 类内:输出运算符操作函数重载
ostream &Time::operator<<(ostream &out)
{out << hour << ":" << minute << ":" << second << endl;return out;
}// 类外:输出运算符操作函数重载
ostream &operator<<(ostream &out, Time &t) // 由于是类外重载,所以有多少参数就需要传入多少个
{// 存在一个矛盾:此时需要调用类内成员,所以类内成员必须为 public,但是这并不符合类成员数据原则out << t.hour << ":" << t.minute << ":" << t.second << endl;return out;
}int main()
{Time t1(1, 50, 33);Time t2(0, 20, 33);Time t3 = t1 + t2;t3.show();// 显然,此时类外重载更加匹配平时使用的习惯t3 << cout; // 类内重载运算符cout << t3 << endl; // 类外重载运算符return 0;
}注意:1、定义非类成员运算符函数重载时,必须保证至少有一个参数是自定义类型2、运算符的操作数必须从左到右一次填入参数列表中
上述重载存在着一个问题:就是进行类外重载时,必须要让类内部成员数据权限变成public,而这并不符合类成员权限原则。所以需要借助后续的友元来进行解决。
前缀运算符重载
#include <iostream>
using namespace std;class Time
{public:int hour;int minute;int second;public:Time(int h = 0, int m = 0, int s = 0): hour(h), minute(m), second(s){};// 加法运算符操作函数重载 (t1 + t2)const Time operator+(const Time &r);// 类内:输出运算符操作函数重载ostream &operator<<(ostream &out);// 前缀运算符操作重载Time & operator++();// 显示时间void show();
};const Time Time::operator+(const Time &r)
{Time tmp;tmp.second = this->second + r.second;if(tmp.second >= 60){tmp.minute++;tmp.second -= 60;}tmp.minute += this->minute + r.minute;if(tmp.minute >= 60){tmp.hour++;tmp.minute -= 60;}tmp.hour += this->hour + r.hour;tmp.hour %= 24;return tmp;
}void Time::show()
{cout << hour << ":" << minute << ":" << second << endl;
}// 类内:输出运算符操作函数重载
ostream &Time::operator<<(ostream &out)
{out << hour << ":" << minute << ":" << second << endl;return out;
}// 类外:输出运算符操作函数重载
ostream &operator<<(ostream &out, Time &t) // 由于是类外重载,所以有多少参数就需要传入多少个
{// 设置宽度为 2,不足则填充为 0out.width(2);out.fill('0');// 存在一个矛盾:此时需要调用类内成员,所以类内成员必须为 public,但是这并不符合类成员数据原则out << t.hour << ":" << t.minute << ":" << t.second << endl;return out;
}// 前缀运算符操作重载
Time & Time::operator++()
{second++;second = second >= 60 ? (minute++, 0) : second;minute = minute >= 60 ? (hour++, 0) : minute;hour %= 24;return *this;
}int main()
{Time t1(1, 50, 33);Time t2(0, 20, 33);Time t3 = t1 + t2;cout << "t3.show()" << endl;t3.show();// 显然,此时类外重载更加匹配平时使用的习惯cout << "t3 << cout" << endl;t3 << cout; // 类内重载运算符cout << "cout << t3 << endl" << endl;cout << t3 << endl; // 类外重载运算符++t1;cout << "++t1" << endl;cout << t1 << endl;return 0;
}
后缀运算符重载
#include <iostream>
using namespace std;class Time
{public:int hour;int minute;int second;public:Time(int h = 0, int m = 0, int s = 0): hour(h), minute(m), second(s){};// 加法运算符操作函数重载 (t1 + t2)const Time operator+(const Time &r);// 类内:输出运算符操作函数重载ostream &operator<<(ostream &out);// 前缀运算符操作重载Time & operator++();// 后缀运算符操作重载const Time operator++(int); // int 没有实际作用,只是用于区分前缀还是后缀// 显示时间void show();
};const Time Time::operator+(const Time &r)
{Time tmp;tmp.second = this->second + r.second;if(tmp.second >= 60){tmp.minute++;tmp.second -= 60;}tmp.minute += this->minute + r.minute;if(tmp.minute >= 60){tmp.hour++;tmp.minute -= 60;}tmp.hour += this->hour + r.hour;tmp.hour %= 24;return tmp;
}void Time::show()
{cout << hour << ":" << minute << ":" << second << endl;
}// 类内:输出运算符操作函数重载
ostream &Time::operator<<(ostream &out)
{out << hour << ":" << minute << ":" << second << endl;return out;
}// 类外:输出运算符操作函数重载
ostream &operator<<(ostream &out, Time &t) // 由于是类外重载,所以有多少参数就需要传入多少个
{// 设置宽度为 2,不足则填充为 0out.width(2);out.fill('0');// 存在一个矛盾:此时需要调用类内成员,所以类内成员必须为 public,但是这并不符合类成员数据原则out << t.hour << ":" << t.minute << ":" << t.second << endl;return out;
}// 前缀运算符操作重载
Time & Time::operator++()
{second++;second = second >= 60 ? (minute++, 0) : second;minute = minute >= 60 ? (hour++, 0) : minute;hour %= 24;return *this;
}// 后缀运算符操作重载
const Time Time::operator++(int)
{// 作出说明1:相较于前缀运算,此时加入 const 是防止出现 t1++ = t2,这一点相较于未重载前冲突// 作出说明2:为什么不返回引用?因为在函数内部创建了一个临时变量来保存原值并返回,那么函数结束会释放销毁,返回引用则找不到对应的地址,所以直接返回临时变量的内部数值Time tmp = *this;second++;second = second >= 60 ? (minute++, 0) : second;minute = minute >= 60 ? (hour++, 0) : minute;hour %= 24;return tmp;
}int main()
{Time t1(1, 50, 33);Time t2(0, 20, 33);Time t3 = t1 + t2;cout << "t3.show()" << endl;t3.show();// 显然,此时类外重载更加匹配平时使用的习惯cout << "t3 << cout" << endl;t3 << cout; // 类内重载运算符cout << "cout << t3 << endl" << endl;cout << t3 << endl; // 类外重载运算符++t1;cout << "++t1" << endl;cout << t1 << endl;t1++;cout << "t1++" << endl;cout << t1 << endl;return 0;
}
友元函数
目的:在类外部非本类成员对类内部非公有数据进行访问。
例如:遥控器仅仅通过自身按钮而非电视机公开按钮去操纵电视机
友元函数并没有破坏封装性原则,应为决定函数是否为友元函数的对象还是类本身
#include <iostream>
using namespace std;class A
{private:int x;public:A(int x = 0) : x(x){}// 声明一个友元函数friend void show(const A &r);
};void show(const A &r)
{cout << r.x << endl;
}int main()
{A a(6);// 友元函数的调用与普通函数一样,不需要类对象引用show(a);return 0;
}注意:1、友元函数可以直接访问类私有成员,且友元函数定义不需要写 friend 关键字
修改上述非类成员(类外函数)运算符重载代码存在的问题如下:
#include <iostream>
using namespace std;class Time
{private:int hour;int minute;int second;public:Time(int h = 0, int m = 0, int s = 0): hour(h), minute(m), second(s){};// 类外:输出运算符操作函数重载friend ostream &operator<<(ostream &out, Time &t); // 显示时间void show();
};void Time::show()
{cout << hour << ":" << minute << ":" << second << endl;
}// 类外:输出运算符操作函数重载
ostream &operator<<(ostream &out, Time &t) // 由于是类外重载,所以有多少参数就需要传入多少个
{out << t.hour << ":" << t.minute << ":" << t.second << endl;return out;
}int main()
{Time t1(1, 50, 33);cout << t1 << endl; // 类外重载运算符return 0;
}
友元类
#include <iostream>
using namespace std;class A
{private:int a;public:void show() { cout << a << endl; }// 将 B 类作为 A 类的友元类friend class B; // B 类中所有类方法都可以访问 A 类中所有成员数据
};class B
{public:void set_A(A &r, int b) { r.a = b; }
};int main()
{A a;B b;b.set_A(a, 6);a.show();return 0;
}
友元类方法
相较于友元类,友元类方法缩小了范围,意思就是在 A 类中只允许 B 类中的部分类方法来开放访问所有成员数据权限。
#include <iostream>
using namespace std;class A
{private:int a;public:void show() { cout << a << endl; }// 将 B 类中的部分类方法作为 A 类的友元类方法friend void B::set_A(A &r, int b); // B 类中仅该类方法可以访问 A 类中所有成员数据
};class B
{public:void set_A(A &r, int b) { r.a = b; }
};int main()
{A a;B b;b.set_A(a, 6);a.show();return 0;
}注意:上述方法极其容易出现未定义等现象,要解决上述问题就要分文件处理,主要可以分为 main.cpp A.cpp A.h B.cpp B.h
相关文章:
c++ 多态性
类的多态 多态概念入门 #include <iostream> using namespace std;/* 多态的前提: 拥有继承关系的类中有相同的函数(返回类型、函数名、形参列表) 多态解决的问题:1、派生类的对象被赋值给基类对象时2、派生类的对象初始化基类的引用时3、基类的指针指向派生…...
块存储、文件存储和对象存储详细介绍
块存储、文件存储和对象存储介绍 块存储:像跑车,因为它们都能提供快速的响应和高性能,适合需要即时数据访问的场景,比如数据库和虚拟化技术。 文件存储:像货车,因为它们都能承载大量货物(文件&…...
移植 AWTK 到 纯血鸿蒙 (HarmonyOS NEXT) 系统 (9) - 编译现有的AWTK应用程序
AWTK 应用程序开发完成后,在配置文件中添加 harmonyos 的选项,通过create_project.py脚本即可生成 DevEco Studio的工程。 安装开发环境 DevEco Studio HarmonyOS 的开发工具。 Python 运行环境。 git 源码管理工具。 下载 awtk 和 awtk-harmonyos…...
ssm基于BS的仓库在线管理系统的设计与实现+vue
系统包含:源码论文 所用技术:SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习,获取源码看文章最下面 需要定制看文章最下面 目 录 第一章 绪论 1 1.1 研究背景 1 1.2 研究意义 1 1.3 研究内容 2 第二章 开发环境与技术3 …...
面试题:Spring(一)
1. Spring框架中bean是单例么? Service Scope("singleton") public class UserServiceImpl implements UserService { }singleton : bean在每个Spring IOC容器中只有一个实例。prototype:一个bean的定义可以有多个实例。 2. Spring框架中的…...
MySQ怎么使用语法介绍(详细)
一、什么是库结构 库结构的意思就是指数据库的结构。所以,理解“库结构”就要先理解“库”是什么。 在数据库的上下文中,库指的是一个数据库。简单来说,数据库(库)是用来存储和管理数据的容器。它不仅存储实际的数据…...
新能源汽车与公共充电桩布局
近年来,全球范围内对新能源汽车产业的推动力度不断增强,中国新能源汽车市场也呈现蓬勃发展的势头,在政策与市场的共同推动下,新能源汽车销量持续增长。然而,据中国充电联盟数据显示,充电基础设施建设滞后于新能源汽车数量增长的现状导致充电桩供需不平衡,公共充电桩服务空白区域…...
【GIT】sourceTree的“当前分支“,“合并分支“与“检出分支的区别
GIT三款经典可视化 由上文文档得出灵感写出此篇 这三个概念在 Git 操作中都是很常见的, 来逐个解析: 1. 当前分支 “当前分支”就是你目前正在工作的分支。你在进行任何代码修改、提交等操作时,都会应用到“当前分支”上。换句话说…...
【Git】如何在 Git 中高效合并分支:完整指南
目录 引言1. 切换到主分支1.1 切换分支命令1.2 相关命令1.3 切换分支示意图 2. 合并分支2.1 基本合并命令2.2 合并选项2.3 合并流程示意图 3. 解决冲突3.1 解决冲突的步骤3.2 相关命令3.3 解决冲突示意图 4. 本地更新分支4.1 拉取远程更改4.2 更新主分支4.3 拉取远程更新到本地…...
成都睿明智科技有限公司抖音电商服务效果如何?
在这个短视频风起云涌的时代,抖音电商以其独特的魅力,成为了众多商家竞相追逐的新蓝海。而在这片波澜壮阔的商海中,成都睿明智科技有限公司犹如一艘稳健的航船,引领着无数企业驶向成功的彼岸。今天,就让我们一起揭开成…...
收集的linux命令/Docker命令/git命令
查看linux发行版本 lsb_release -a显示操作系统的发行版号 uname -r1. 启动 Docker。 sudo systemctl start docker2. 通过运行映像来验证 Docker 引擎安装是否成功。hello-world sudo docker run hello-world查看docker版本 docker -v查看docker配置信息 docker infodoc…...
DNS域名解析实验
准备工作 [rootlocalhost ~]# setenforce 0 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# mount /dev/sr0 /mnt [rootlocalhost ~]# dnf install bind -y DNS正向解析: 对主配置文件进行修改 [rootlocalhost ~]# vim /etc/named.conf 正向解析…...
Dify 本地部署指南
一、前置条件 Clone Dify 代码: git clone https://github.com/langgenius/dify.git 在启用业务服务之前,我们需要先部署 PostgresSQL / Redis / Weaviate(如果本地没有的话),可以通过以下命令启动: cd…...
15分钟学 Go 第 38 天:数据库基础
第38天 - 数据库基础 学习目标 学习如何连接和操作数据库,包括基本的增、删、改、查功能,以及如何使用Go语言中的database/sql包进行数据库交互。 内容概述 在现代应用程序中,数据库是数据持久化的重要部分。Go语言通过database/sql包提供…...
【Python】图片处理
一、获取图片尺寸 优点缺点Pillow功能丰富,支持多种图像处理操作。使用简单,适合快速原型开发。对于处理大型图像或批量图像时,性能可能不如OpenCV。OpenCV性能强大,适合处理大型图像和视频处理。提供了丰富的计算机视觉算法。相…...
面相小白的php反序列化漏洞原理剖析
前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理反序列化漏洞的一些成因原理 建议学习反序列化之前 先对php基础语法与面向对象有个大体的了解 (我觉得我整理的比较细致,了解这俩是个啥就行) 漏洞实战情况 这个漏洞黑盒几乎不会被发现&am…...
文本转SQL(Text-to-SQL),场景介绍与 Spring AI 实现
在众多的 AI 大模型的应用场景中,Text-to-SQL,也就是文本转 SQL,是其中实用性很高的一个。Text-to-SQL 充分利用了大模型的优势,把用户提供的自然语言描述转换成 SQL 语句,还可以执行生成的 SQL 语句,再把查…...
科研绘图系列:R语言组合堆积图(stacked plot)
文章目录 介绍加载R包数据数据预处理画图1画图2组合图形系统信息介绍 堆积图(Stacked Chart),也称为堆叠图,是一种常用的数据可视化图表,主要用于展示不同类别的数据量在总体中的分布情况。堆积图可以是柱状图、条形图或面积图的形式,其中各个类别的数据量被叠加在一起,…...
YOLOv11及自研模型更新汇总
YOLOv11使用教程:YOLOv11入门到入土使用教程(含结构图) 缝合教程:深度学习模块创作(缝合)教程|适合1-360月小宝宝食用,干货满满 YOLO中的yaml文件详解:https://xy2668825911.blog.csdn.net/article/details…...
系统安全架构
一个完整的信息安全系统至少包含三类措施: 技术方面的安全措施, 管理方面的安全措施 相应的政策法律。 网络安全威胁 授权侵犯:为某一特权使用一个系统的人却将该系统用作其他未授权的目的。假冒:一个实体(人或系统)假装成另一个实体非法…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
