面向对象程序设计之继承(C++)
1.继承的定义
1.1继承的概念
继承(inheritance)机制是⾯向对象程序设计使代码可以复⽤的最重要的⼿段,它允许我们在保持原有类特性的基础上进⾏扩展,增加⽅法(成员函数)和属性(成员变量),这样产⽣新的类,称派⽣类。继承 呈现了⾯向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的函数层次的复⽤,继承是类设计层次的复⽤
#include<iostream>using namespace std;
//基类
class Person
{
public:// 进⼊校园/图书馆/实验室刷⼆维码等⾝份认证 void identity(){cout << "void identity()" << _name << endl;}
protected:string _name = "张三"; // 姓名 string _address; // 地址 string _tel; // 电话 int _age = 18; // 年龄
};
//派生类
class Student : public Person
{
public:// 学习 void study(){// ...}
protected:int _stuid; // 学号
};
class Teacher : public Person
{
public:// 授课 void teaching(){//...}
protected:string title; // 职称
};int main()
{Student s;Teacher t;//继承基类的公有函数与保护成员s.identity();t.identity();return 0;
}
1.2 继承定义格式
下⾯我们看到Person是基类,也称作⽗类。Student是派⽣类,也称作⼦类。(因为翻译的原因,所以 既叫基类/派⽣类,也叫⽗类/⼦类)
1.3继承基类成员访问⽅式的变化
注意:继承后的派生类继承了基类中的所有成员,不过有特定的成员因为权限不可被访问
1. 基类private成员在派⽣类中⽆论以什么⽅式继承都是不可⻅的。这⾥的不可⻅是指基类的私有成员还是被继承到了派⽣类对象中,但是语法上限制派⽣类对象不管在类⾥⾯还是类外⾯都不能去访问它
2. 基类private成员在派⽣类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派⽣类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。
3. 实际上⾯的表格我们进⾏⼀下总结会发现,基类的私有成员在派⽣类都是不可⻅。基类的其他成员在派⽣类的访问⽅式==Min(成员在基类的访问限定符,继承⽅式),public >protected> private
4. 使⽤关键字class时默认的继承⽅式是private,使⽤struct时默认的继承⽅式是public,不过最好显示的写出继承⽅式。
5. 在实际运⽤中⼀般使⽤都是public继承,⼏乎很少使⽤protetced/private继承,也不提倡使⽤ protetced/private继承,因为protetced/private继承下来的成员都只能在派⽣类的类⾥⾯使⽤,实际中扩展维护性不强
派生类不可以访问基类中的私有成员,但是可以使用基类的公有成员函数调用访问私有成员
class Parent
{
public:void GetNum(){cout << num << endl;}
private:int num = 1;
};class Child : public Parent
{
public:void GetRet(){cout << ret << endl;}
private:int ret = 2;
};int main()
{Parent p;Child c;p.GetNum();c.GetNum();return 0;
}
1.4类模版的继承
使用类模版模拟实现一个栈,可以使用vector/list/deque来当做底层容器,核心就是类模版的继承
template<class T>
class Stack : public std::vector<T>
//class Stack : public std::list<T>
//class Stack : public std::deque<T>
{
public:// 基类是类模板时,需要指定⼀下类域, // 否则编译报错:error C3861: “push_back”: 找不到标识符 // 因为stack<int>实例化时,也实例化vector<int>了 // 但是模版是按需实例化,push_back等成员函数未实例化,所以找不到 void push(const T& x){vector<T>::push_back(x);}void pop(){vector<T>::pop_back();}const T& top(){return vector<T>::back();}bool empty(){return vector<T>::empty();}
};int main()
{Stack<int> st;st.push(1);st.push(2);st.push(3);st.push(4);while (!st.empty()){cout << st.top() << " ";st.pop();}cout << endl;return 0;
}
2.基类与派生类的转换
1.public继承的派⽣类对象可以赋值给基类的指针、基类的引⽤。这⾥有个形象的说法叫切⽚或者切割。寓意把派⽣类中基类那部分切出来,基类指针或引⽤指向的是派⽣类中切出来的基类那部分
2.基类对象不能赋值给派⽣类对象
3.基类的指针或者引⽤可以通过强制类型转换赋值给派⽣类的指针或者引⽤。但是必须是基类的指针是指向派⽣类对象时才是安全的。这⾥基类如果是多态类型,可以使⽤RTTI(Run-Time-Type-Information)的dynamic_cast)来进⾏识别后进⾏安全转换
3.作用域
基类与派生类都具有不同的作用域,所以不存在重载,因为重载需要在相同的作用域
1. 在继承体系中基类和派⽣类都有独⽴的作⽤域
2. 派⽣类和基类中有同名成员,派⽣类成员将屏蔽基类对同名成员的直接访问,这种情况叫隐藏(在派⽣类成员函数中,可以使⽤基类::基类成员显示访问)
3. 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏,不论参数相同与否
4. 注意在实际中在继承体系⾥⾯最好不要定义同名的成员
通过子类调用继承父类的同名函数,如果父类的函数被隐藏则会报错,需要显示指定作用域
class Parent
{
public:void fun(){cout << "fun()" << endl;}
};class Child : public Parent
{
public:void fun(int i){cout << "fun(i)" << endl;}
};int main()
{Parent p;Child c;//报错,因为子类中没有参数为空的fun函数,而继承父类中的fun函数被隐藏,所以会报错,指定作用域即可//c.fun();c.Parent::fun();return 0;
}
4.派生类的默认成员函数
6个默认成员函数,默认的意思就是指我们不写编译器会变我们⾃动⽣成⼀个,那么在派⽣类中,这⼏个成员函数是如何⽣成的呢
扩展:初始化的顺序与初始化列表顺序无关,与声明顺序有关
首先回顾一下默认构造完成的操作:
1.对内置类型:不确定
2.对自定义类型:调用默认构造
3.对从基类继承的类型: 将继承而来的成员看做一个整体,调用基类的默认构造
1.派⽣类的构造函数必须调⽤基类的构造函数初始化基类的那⼀部分成员。如果基类没有默认的构造函数,则必须在派⽣类构造函数的初始化列表阶段显示调⽤
class Parent
{
public://Parent(const char* name = "zhangsan")//基类没有默认构造函数Parent(const char* name):_name(name){cout << "Parent(const char* name)" << endl;}Parent(const Parent& p):_name(p._name){cout << "Parent(const Parent& p)" << endl;}Parent& operator=(const Parent& p){cout << "Parent& operator=(const Parent& p)" << endl;if (this != &p){_name = p._name;}return *this;}~Parent(){cout << "~Parent()" << endl;}
private:string _name;
};class Child : public Parent
{
public:Child(const char* name,int num):Parent(name)//显示初始化,_num(num){cout << "Child(const char* name,int num)" << endl;}private:int _num;
};
2.派⽣类的拷⻉构造函数必须调⽤基类的拷⻉构造完成基类的拷⻉初始化
对于内置类型:值拷贝
对于自定义类型:默认拷贝构造
对于继承而来的父类成员:调用父类的拷贝构造
所以一般来说子类使用默认拷贝构造函数即可,除非开辟了新的空间需要自定义拷贝构造
class Parent
{
public://Parent(const char* name = "zhangsan")//基类没有默认构造函数Parent(const char* name):_name(name){cout << "Parent(const char* name)" << endl;}Parent(const Parent& p):_name(p._name){cout << "Parent(const Parent& p)" << endl;}Parent& operator=(const Parent& p){cout << "Parent& operator=(const Parent& p)" << endl;if (this != &p){_name = p._name;}return *this;}~Parent(){cout << "~Parent()" << endl;}
private:string _name;
};class Child : public Parent
{
public:Child(const char* name,int num):Parent(name),_num(num){cout << "Child(const char* name,int num)" << endl;}Child(const Child& c):Parent(c),_num(c._num){cout << "Child(const Child& c)" << endl;}private:int _num;
};
3.派⽣类的operator=必须要调⽤基类的operator=完成基类的复制。需要注意的是派⽣类的 operator=隐藏了基类的operator=,所以显示调⽤基类的operator=,需要指定基类作⽤域
class Parent
{
public://Parent(const char* name = "zhangsan")//基类没有默认构造函数Parent(const char* name):_name(name){cout << "Parent(const char* name)" << endl;}Parent(const Parent& p):_name(p._name){cout << "Parent(const Parent& p)" << endl;}Parent& operator=(const Parent& p){cout << "Parent& operator=(const Parent& p)" << endl;if (this != &p){_name = p._name;}return *this;}~Parent(){cout << "~Parent()" << endl;}
private:string _name;
};class Child : public Parent
{
public:Child(const char* name,int num):Parent(name),_num(num){cout << "Child(const char* name,int num)" << endl;}Child(const Child& c):Parent(c),_num(c._num){cout << "Child(const Child& c)" << endl;}Child& operator=(const Child& c){cout << "Child& operator=(const Child& c)" << endl;if (this != &c){//子类和父类的operator=构成隐藏关系Parent::operator=(c);_num = c._num;}return *this;}private:int _num;
};
4.派⽣类的析构函数会在被调⽤完成后⾃动调⽤基类的析构函数清理基类成员。因为这样才能保证派⽣类对象先清理派⽣类成员再清理基类成员的顺序
5.派⽣类对象初始化先调⽤基类构造再调派⽣类构造
6.派⽣类对象析构清理先调⽤派⽣类析构再调基类的析构
class Parent
{
public://Parent(const char* name = "zhangsan")//基类没有默认构造函数Parent(const char* name):_name(name){cout << "Parent(const char* name)" << endl;}Parent(const Parent& p):_name(p._name){cout << "Parent(const Parent& p)" << endl;}Parent& operator=(const Parent& p){cout << "Parent& operator=(const Parent& p)" << endl;if (this != &p){_name = p._name;}return *this;}~Parent(){cout << "~Parent()" << endl;}
private:string _name;
};class Child : public Parent
{
public:Child(const char* name,int num):Parent(name),_num(num){cout << "Child(const char* name,int num)" << endl;}Child(const Child& c):Parent(c),_num(c._num){cout << "Child(const Child& c)" << endl;}Child& operator=(const Child& c){cout << "Child& operator=(const Child& c)" << endl;if (this != &c){Parent::operator=(c);_num = c._num;}return *this;}~Child(){ //子类与父类的析构构成隐藏关系,不需要显式调用//Parent::~Parent();cout << "~Child()" << endl;}
private:int _num;
};
7.因为多态中⼀些场景析构函数需要构成重写,重写的条件之⼀是函数名相同。那么编译器会对析构函数名进⾏特殊处理,处理成destructor(),所以基类析构函数不加virtual的情况下,派⽣类析构函数和基类析构函数构成隐藏关系
5.不可被继承的基类
方法一:将父类的构造函数私有化,这样子类就无法实例化对象
//方法一:将基类的构造函数私有化,这样派生类就无法实例化对象
class Parent
{
private:Parent(){cout << "Parent()" << endl;}
};class Child :public Parent
{
public:Child(){cout << "Child()" << endl;}
};
方法二:C++11新增了final关键字,使得基类不可以被继承
//方法二:C++11新增了final关键字,使得基类不可被继承
class Parent final
{
public:Parent(){}
};class Child :public Parent
{
public:Child(){}
};int main()
{Child c;return 0;
}
6.继承与友元
友元不能被继承,也就是说父类的友元不可以访问子类的私有和保护成员,除非是子类与父类共同的友元
//友元不可被继承,父类的友元不能访问子类的保护与私有成员//前置声明
class Child;class Parent
{void friend Display(const Parent& p, const Child& c);
protected:int _parent;
};class Child :public Parent
{
protected:int _child;
};void Display(const Parent& p, const Child& c)
{cout << p._parent << endl;cout << c._child << endl;
}
7.继承与静态成员
基类定义了一个静态成员,那么无论有多少子类都只有一个静态变量成员,即一个static实例
//继承与静态成员
//父类中定义一个静态成员,无论派生出多少子类都只有一个static实例
class Parent
{
public:static int _parent;
};int Parent::_parent = 0;class Child :public Parent
{
public:int _child;
};int main()
{Parent p;Child c;cout << &p._parent << endl;cout << &c._parent << endl;cout << &c._child << endl;return 0;
}
8.多继承及菱形继承
8.1继承模型
1.单继承:⼀个派⽣类只有⼀个直接基类时称这个继承关系为单继承
2.多继承:⼀个派⽣类有两个或以上直接基类时称这个继承关系为多继承,多继承对象在内存中的模型是,先继承的基类在前⾯,后⾯继承的基类在后⾯,派⽣类成员在放到最后⾯。
3.菱形继承:菱形继承是多继承的⼀种特殊情况。菱形继承有数据冗余和⼆义性的问题,⽀持多继承就 ⼀定会有菱形继承,像Java就直接不⽀持多继承,规避掉了这⾥的问题,所以实践中我们也是不建议设计出菱形继承这样的模型的
//菱形继承
class Base
{
public:int _base;
};class Mother :public Base
{
public:int _mother;
};class Father :public Base
{
public:int _father;
};class Child :public Father, public Mother
{
public:int _child;
};int main()
{Child c;cout << c._base << endl;return 0;
}
这里由于菱形继承所以无法确定访问的_base是哪个类里的成员变量
8.2虚继承
使用virtual关键字来完成虚继承,确保一个变量只存在一个定义,避免二义性,一般地如果有多个子类连续菱形继承,只对继承父类的第一批子类进行virtual关键字修饰,即对产生数据冗余的类进行虚继承即可
//2.虚继承
class Base
{
public:int _base;
};class Mother : virtual public Base
{
public:int _mother;
};class Father : virtual public Base
{
public:int _father;
};class Child :public Father, public Mother
{
public:int _child;
};int main()
{Child c;Base b;Father f;Mother m;cout << &c._base << endl;cout << &b._base << endl;cout << &f._base << endl;cout << &m._base << endl;return 0;
}
8.3继承后的指针偏移问题
根据下图我们知道Derive继承了Base1与Base2,其中p3自然指向的是Base1,p1由于是Base1继承而来,就与p3指向同一个位置,而p2则是由于切片后指向的是p1与p3的下一个位置,所以三者的内存地址是:p1==p3!=p2
//继承中的指针偏移问题
class Base1
{
public:int _b1;
};class Base2
{
public:int _b2;
};class Derive : public Base1, public Base2
{int _d;
};int main()
{Derive d;Base1* p1 = &d;Base2* p2 = &d;Derive* p3 = &d;cout << &p1 << endl;cout << &p2 << endl;cout << &p3 << endl;return 0;
}
9.继承与组合
public继承是⼀种is-a的关系。也就是说每个派⽣类对象都是⼀个基类对象
• 组合是⼀种has-a的关系。假设B组合了A,每个B对象中都有⼀个A对象
• 继承允许你根据基类的实现来定义派⽣类的实现。这种通过⽣成派⽣类的复⽤通常被称为⽩箱复⽤ (white-box-reuse)。术语“⽩箱”是相对可视性⽽⾔:在继承⽅式中,基类的内部细节对派⽣类可⻅。继承⼀定程度破坏了基类的封装,基类的改变,对派⽣类有很⼤的影响。派⽣类和基类间的依赖关系很强,耦合度⾼
• 对象组合是类继承之外的另⼀种复⽤选择。新的更复杂的功能可以通过组装或组合对象来获得。对象组合要求被组合的对象具有良好定义的接⼝。这种复⽤⻛格被称为⿊箱复⽤(black-box-reuse),因为对象的内部细节是不可⻅的。对象只以“⿊箱”的形式出现。组合类之间没有很强的依赖关系,耦合度低。优先使⽤对象组合有助于你保持每个类被封装。
• 优先使⽤组合,⽽不是继承。实际尽量多去⽤组合,组合的耦合度低,代码维护性好。不过也不太那么绝对,类之间的关系就适合继承(is-a)那就⽤继承,另外要实现多态,也必须要继承。类之间的关系既适合⽤继承(is-a)也适合组合(has-a),就⽤组合。
template<class T>class vector{};// stack和vector的关系,既符合is-a,也符合has-a template<class T>class stack : public vector<T>
{};template<class T>class stack{public:vector<T> _v;
};int main()
{return 0;
}
相关文章:

面向对象程序设计之继承(C++)
1.继承的定义 1.1继承的概念 继承(inheritance)机制是⾯向对象程序设计使代码可以复⽤的最重要的⼿段,它允许我们在保持原有类特性的基础上进⾏扩展,增加⽅法(成员函数)和属性(成员变量),这样产⽣新的类,称派⽣类。继承 呈现了⾯向…...

IAPP发布《2024年人工智能治理实践报告》
文章目录 前言一、黑箱问题►透明度、可理解性与可解释性二、法律和政策中的注意事项►欧盟的《通用数据保护条例》►欧盟的AI法案►NIST的AI风险管理框架►美国的第14110号行政命令►《生成式人工智能服务管理暂行办法》►新加坡的AI验证三、实施人工智能治理►模型卡与系统卡…...

了解MySQL 高可用架构:主从备份
为了防止数据库的突然挂机,我们需要对数据库进行高可用架构。主从备份是常见的场景,通常情况下都是“一主一从/(多从)”。正常情况下,都是主机进行工作,从机进行备份主机数据,如果主机某天突然意外宕机,从机…...

[OpenCV] 数字图像处理 C++ 学习——15像素重映射(cv::remap) 附完整代码
文章目录 前言1.像素重映射理论基础2.代码实现(1) remap()细节(2)水平翻转(2)垂直翻转(3)旋转 180 度(4)径向扭曲 3.完整代码 前言 像素重映射将图像中的每个像素映射到新位置,实现图像的扭曲、校正等操作。在 OpenCV 中,cv::remap() 函数就是用于实现这…...
Oreace每日运维操作
一.Oreace每日运维操作 目录 一.Oreace每日运维操作 1.1、确认所有的INSTANCE状态正常 1.2、检查文件系统的使用(剩余空间) 1.3 lwh暗码,,、检查日志文件和trace文件记录 1.4 lwh、检查数据库当日备份…...

【XR】AR HUD
1. AR HUD(head up display)原理 目标: 产业链上的各大Tier1及PGU企业都在积极开发这一技术,许多厂家已推出LCOS样机,比如说水晶光电、华阳集团、瀚思通、疆程已在北京车展或去年的上海车展上展出了LCOS方案的AR-HUD样…...
C/C++内存管理——内存泄漏/内存碎片
一、什么是内存泄漏 内存泄漏指的是在程序运行过程中,已经分配给程序使用的内存没有得到及时和正确的释放,导致这部分内存无法被程序再次使用或者被操作系统回收。内存泄漏通常发生在动态分配的内存上,如果这部分内存没有被正确释放,随着时间的推移,越来越多的内存将被占…...

使用 GaLore 预训练LLaMA-7B
项目代码: https://github.com/jiaweizzhao/galorehttps://github.com/jiaweizzhao/galore 参考博客: https://zhuanlan.zhihu.com/p/686686751 创建环境 基础环境配置如下: 操作系统: CentOS 7CPUs: 单个节点具有 1TB 内存的 Intel CP…...
gitlab无法push(pre-receive hook declined)
如果是个人的项目,托管在官网,可以参考这位大佬的, GitLab新建项目后push reject提交失败的解决办法_push rejected-CSDN博客 如果是公司的项目,去项目成员里看自己的身份,如果只是developer,是无法push到…...

物品识别——基于python语言
目录 1.物品识别 2.模型介绍 3.文件框架 4.代码示例 4.1 camera.py 4.2 interaction.py 4.3 object_detection.py 4.4 main.py 4.5 运行结果 5.总结 1.物品识别 该项目使用Python,OpenCV进行图像捕捉,进行物品识别。我们将使用YOLO(…...

【PostgreSQL】安装及使用(Navicat/Arcgis),连接(C#)
简介 PostgreSQL 是一个功能强大的开源对象关系数据库系统 下载地址 PostgreSQL: Downloads 由于我电脑上安装的是arcgispro3.1所以需要下载对应的postgresql版本 PostgreSQL 12 对应的 PostGIS 版本主要是 3.5.0 或更高版本。 安装 一般设置为postgresql 安装扩展插件 此…...

第L6周:机器学习-随机森林(RF)
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 目标: 1.什么是随机森林(RF) 随机森林(Random Forest, RF)是一种由 决策树 构成的 集成算法 &#…...

【电路笔记】-差分运算放大器
差分运算放大器 文章目录 差分运算放大器1、概述2、差分运算放大器表示2.1 差分模式2.2 减法器模式3、差分放大器示例3.1 相关电阻3.2 惠斯通桥3.3 光/温度检测4、仪表放大器5、总结1、概述 在之前的文章中,我们讨论了反相运算放大器和同相运算放大器,我们考虑了在运算放大器…...
git 命令---想要更改远程仓库
在 Git 中,origin 是默认的远程仓库名称。可以使用以下命令查看当前 Git 仓库的 origin 名称及其对应的 URL: git remote -v这个命令会列出所有配置的远程仓库及其名称,其中 origin 通常是克隆时自动设置的默认远程仓库名称。输出示例&#…...
LeetCode:2848. 与车的相交点 一次遍历,时间复杂度O(n)
2848. 与车的相交点 today 2848. 与车的相交点 题目描述 给你一个下标从 0开始的二维整数数组 nums 表示汽车停放在数轴上的坐标。对于任意下标 i ,nums[i] [starti, endi] ,其中 s t a r t i start_i starti 是第 i 辆车的起点, e n …...

Xcode 16 RC (16A242) 发布下载,正式版下周公布
Xcode 16 RC (16A242) - Apple 平台 IDE IDE for iOS/iPadOS/macOS/watchOS/tvOS/visonOS 请访问原文链接:https://sysin.org/blog/apple-xcode-16/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org Xcode 16 的新功…...

git 更换远程地址的方法
需要将正在开发的代码远程地址改成新的地址,通过查询发现有三个方法可以实现,特此记录。具体方法如下: (1)通过命令直接修改远程仓库地址 git remote 查看所有远程仓库git remote xxx 查看指定远程仓库地址git remote…...

9. 什么是 Beam Search?深入理解模型生成策略
是不是总感觉很熟悉? 在之前第5,7,8篇文章中,我们都曾经用到过与它相关的参数,而对于早就有着实操经验的同学们,想必见到的更多。这篇文章将从示例到数学原理和代码带你进行理解。 Beam Search 对应的中文翻…...
Spring自定义注解
目录 一、interface 关键字 二、元注解 三、简单实现 四、使用切面执行自定义注解逻辑 1) 首先将刚才的注解修改成放在方法上的: 2) 定义一个切面类: 3)将注解放入到接口方法中测试: 五、切点表达式 一、interface 关键字 …...

微信小程序:wx.login或调用uni.login时报错the code is a mock one
微信小程序,调用wx.login或调用uni.login方法,返回the code is a mock one 原因与解决 原因:没有关联真实的 appid,解决办法:绑定真实的微信小程序的appid...

关于akka官方quickstart示例程序(scala)的记录
参考资料 https://doc.akka.io/libraries/akka-core/current/typed/actors.html#first-example 关于scala语法的注意事项 extends App是个语法糖,等同于直接在伴生对象中编写main 方法对象是通过apply方法创建的,也可以通过对象的名称单独创建&#x…...
OD 算法题 B卷【BOSS的收入】
文章目录 BOSS的收入 BOSS的收入 一个公司只有一个boss,其有若干一级分销,一级分销又有若干二级分销,每个分销只有唯一的上级;每个月,下级分销需要将自己的总收入(自己的下级上交的)࿰…...
Android 轻松实现 增强版灵活的 滑动式表格视图
表格视图组件,支持: 1. 无标题模式:只有数据行也可以正常滑动 2. 两种滑动模式:固定第一列 或 全部滑动 3. 全面的样式自定义能力 4. 智能列宽计算 1. 无标题模式支持 设置无标题:调用 setHeaderData(null) 或 …...

springboot mysql/mariadb迁移成oceanbase
前言:项目架构为 springbootmybatis-plusmysql 1.部署oceanbase服务 2.springboot项目引入oceanbase依赖(即ob驱动) ps:删除原有的mysql/mariadb依赖 <dependency> <groupId>com.oceanbase</groupId> …...
群晖NAS套件历史版本资源
有时候需要下载历史的群晖套件,可以通过以下地址前往 Synology Archive Download Site - Index of /download 该页面汇集了各类群晖应用程序的过往版本,方便用户根据需要选择特定版本的软件进行下载安装。这种方式适用于需要旧版软件兼容性或进行版本回…...
【高频面试题】快慢指针及相关应用
文章目录 1 简介2 相关应用3 相关题目4 典型例题4.1 判断链表是否有环4.2 寻找链表的入环点4.3 寻找链表的中点4.4 寻找链表的倒数第k个节点4.5 重排链表 (反转链表找链表中点合并链表)4.6 寻找重复数(快慢指针 or 二分)4.7 回文链…...
SQL 中 JOIN 的执行顺序优化指南
SQL 中 JOIN 的执行顺序优化指南 一、JOIN 执行顺序基础原理 在 SQL 查询中,JOIN的执行顺序是查询优化的重要环节。数据库引擎会根据多种因素决定最优的 JOIN 顺序: 逻辑执行顺序:SQL 语句的书写顺序(如 FROM → WHERE → GROUP BY)并不代表实际执行顺序物理执行顺序:由查…...

Starrocks中RoaringBitmap杂谈
背景 最近在阅读Starrocks源码的时候,遇到ColumnRefSet的RoaringBitmap使用,所以借此来讨论一下RoaringBitmap这个数据结构,这种思想是很值得借鉴的。 对于的实现可以参考一下 <dependency><groupId>org.roaringbitmap</groupId><…...
浅谈边缘计算
(꒪ꇴ꒪ ),Hello我是祐言QAQ我的博客主页:C/C语言,数据结构,Linux基础,ARM开发板,网络编程等领域UP🌍快上🚘,一起学习,让我们成为一个强大的攻城狮࿰…...
【论文阅读笔记】Text-to-SQL Empowered by Large Language Models: A Benchmark Evaluation
文章目录 Text-to-SQL Empowered by Large Language Models: A Benchmark Evaluation一、论文基本信息1. 文章标题2. 所属刊物/会议3. 发表年份4. 作者列表5. 发表单位 二、摘要三、解决问题四、创新点五、自己的见解和感想六、研究背景七、研究方法(模型、实验数据…...