成都制作手机网站/什么是seo是什么意思
多态
多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。
需要区分一下:1、菱形虚拟继承,是在继承方式前面加上virtual
;
class Person {};
class Student : virtual public Person {};
class Teacher : virtual public Person {};
class Assistant : public Student, public Teacher {};
2、而多态是单继承中,某个函数接口前面加上virtual
。
class Person {
public://虚函数virtual void BuyTicket() { cout << "Person-买票-全价" << endl; }
};
class Student : public Person {
public://虚函数的重写virtual void BuyTicket() { cout << "Student-买票-半价" << endl; }
};
多态调用
普通调用:跟要调用这个函数的对象类型有关;
多态调用:跟指针或者引用指向的对象有关。
//引用
void func(Person& p)//普通调用的话,都是调用Person类所指向的函数,这里是多态
{p.BuyTicket();//跟指针或者引用指向的对象不同调用不同的虚函数
}
int main()
{Person adult;Student stu;//两个不同类对象调用同一个函数,看一下多态的实验结果func(adult);//引用指向的对象是Person类,故输出 adult-买票-全价func(stu);//引用指向的对象是Student类,故输出 Student-买票-半价return 0;
}
------------------------------------
//指针
void func(Person* p)//多态
{p.BuyTicket();//跟指针或者引用指向的对象不同调用不同的虚函数
}
int main()
{Person adult;Student stu;func(&adult);//输出 adult-买票-全价func(&stu);//输出 Student-买票-半价return 0;
}
所以多态是根据指针/引用指向对象的类型来决定调用某个重写的虚函数。如果函数变成void func(Person p);
【不是引用也不是指针】就不是多态了。
多态的构成条件
- 必须通过父类的指针或者引用调用虚函数;【父类对象不可以】
- 被调用的函数必须是虚函数,且子类必须对父类的虚函数进行重写。
class Person
{
public:virtual void BuyTicket(){cout << "全票" << endl;}
};class Student :public Person
{
public:virtual void BuyTicket(){cout << "学生票" << endl;}
};void func(Person& p)//对于该函数,看到的都是父类对象,子类对象中则为父类对象那一部分切割或者切片出来的,但是多态,可以让p根据指向或者引用的对象来调用不同的重写函虚数
{p.BuyTicket();
}int main()
{Person adult;Student stu;//两个不同类对象调用同一个函数func(adult);func(stu);return 0;
}
注意:切割(切片)是子类对象可以赋值给父类对象/指针/引用。就是拿着子类对象中父类的那一部分,调用父类的拷贝构造再生成一个父类。
虚函数
即被virtual修饰的类成员函数称为虚函数。子类的虚函数可以不加virtual。
即三同【函数名、参数、返回值】函数满足多态的条件为:1、父类虚函数,子类虚函数;2、父类虚函数,子类该同名函数不加virtual。
注意:父类不加virtual,子类加virtual;父类和子类都不加virtual;这两种情况都不满足多态的条件。
可以写为虚函数的有:析构函数【很推荐】、内联函数【写成虚函数后,就不是内联函数了】
不可以是虚函数的有:友元函数、构造函数、static类型的成员函数;子类不一定要重新定义父类的虚函数,视情况而定。
虚函数的重写-三同
虚函数的重写(覆盖):子类中有一个跟父类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名、参数列表完全相同),称子类的虚函数重写了父类的虚函数。
例外1:协变
三同中,返回值不同,但要求返回值必须是父类/子类(包括自己和其他类)的指针或引用。
派生类重写基类虚函数时,与基类虚函数返回值类型不同。即父类虚函数返回父类对象的指针或者引用,子类虚函数返回子类对象的指针或者引用;或者父类虚函数和子类虚函数均返回父类对象的指针或应用;或者父类虚函数返回其他父类的指针或引用,子类虚函数返回其他子类对象的指针或引用;或者父类虚函数和子类虚函数均返回其他父类对象的指针或应用。
例外2:析构函数建议重写
三同中,看似函数名不同,实际上相同,均为destructor
。如果基类的析构函数为虚函数,此时派生类析构函数只要定义,无论是否加virtual关键字,都与基类的析构函数构成重写,虽然基类与派生类析构函数名字不同。虽然函数名不相同,看起来违背了重写的规则,其实不然,这里可以理解为编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一处理成destructor
。
//类A的对象析构会先调用~A
class A
{
public:~A(){delete[] _a;cout << "A析构";}
protected:int* _a = new int[10];
};
//类B的对象析构会先调用~B,再自动调用~A
class B:public A
{
public:~B(){delete[] _b;cout << "B析构";}
protected:int* _b = new int[10];
};
int main()
{A* ptr1 = new A;A* ptr2 = new B;//这是普通调用!根据参数类型来调用,类型都是A*delete ptr1;//调用A的析构函数delete ptr2;//调用A的析构函数//存在内存泄漏问题----------virtual ~A() {};//将A的析构函数变成虚函数,B的也加上//此时是多态调用!根据指针所指向的类型来调用delete ptr1;//调用A的析构函数delete ptr2;//调用B的析构函数,再调用A的析构函数return 0;
}
分析此处delete行为【使用 delete
释放 C++ 类对象的内存时,将在释放该对象的内存之前调用该对象的析构 函数(如果该对象具有析构函数)】:1、使用指针调用析构函数;2、operator delete(ptr);
建议:父类的虚构函数无脑加virtual
,即可构成重写,避免内存泄漏。
如何实现一个不能被继承的类?
- 父类的构造函数设成私有成员函数【C++98的方法】
- 在类定义时+final【C++11的方法】
class Person final {};
此时Person称为最终类。
final和override
final
:修饰父类虚函数,表示该虚函数不能再被重写【既可以修饰类-不能被继承,也可以修饰父类虚函数–不能被重写】
override
: 检查子类虚函数是否重写了父类某个虚函数,如果没有重写编译报错。
再次区分重写(覆盖)、隐藏(重定义)、重载
隐藏(重定义):父类和子类的函数,函数名(1同)即可;
重写(覆盖):父类和子类的虚函数,返回值、函数名、参数列表(3同)即可;
重载:同一个作用域,函数名相同(1同),返回值和参数列表不同
抽象类(纯虚函数)
包含纯虚函数的类叫做抽象类(也叫接口类)。【在虚函数的后面写上 = 0
,则这个函数为纯虚函数。】
- 抽象类不能实例化出对象,子类继承后也不能实例化出对象。
- 只有重写/实现纯虚函数,派生类才能实例化出对象(此时子类对象中也包含了父类对象)。
- 纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。
- override是检查重写,而抽象类是强制重写。
- 纯虚函数可以有函数体
如果一个类在实际生活中没有具体的对象,可以考虑将这个类定义为抽象类。
接口继承和实现继承
- 普通函数的继承是一种实现继承,派生类继承了基类函数,可以使用函数,继承的是函数的实现。
- 虚函数的继承是一种接口继承,派生类继承的是基类虚函数的接口,目的是为了重写,达成多态,继承的是接口。所以如果不实现多态,不要把函数定义成虚函数。
牢记:多态是接口继承,子类用的是父类的虚函数接口!!
//情况1:构成多态
class A
{
public:virtual void func(int val = 1){ std::cout<<"A->"<< val <<std::endl;}virtual void test(){ func();}//this->func()//这里是父类指针this(类型为A*)调用该虚函数,且该虚函数已经完成重写,此时符合多态调用//多态调用是看实际指向对象的类型,p是子类对象的指针B*,故调用的是B类的func函数//因为多态调用是接口继承,故使用的是A类的func接口(用A类的缺省参数)
};
class B : public A
{
public:void func(int val=0){ std::cout<<"B->"<< val <<std::endl; }
};
int main(int argc ,char* argv[])
{B*p = new B;p->test();//输出结果是B->1return 0;
}
//情况2:不构成多态
class A
{
public:virtual void func(int val = 1){ std::cout<<"A->"<< val <<std::endl;}
};
class B : public A
{
public:void func(int val=0){ std::cout<<"B->"<< val <<std::endl; } virtual void test(){ func();}//this->func,func是B*类型,所以不构成多态【多态要求是父类指针/引用调用】
};
int main(int argc ,char* argv[])
{B*p = new B;p->test();//输出结果是B->0return 0;
}
//情况3:不构成多态
class A
{
public:virtual void func(int val = 1){ std::cout<<"A->"<< val <<std::endl;}
};
class B : public A
{
public:void func(int val=0){ std::cout<<"B->"<< val <<std::endl; } virtual void test(){ func();}//this->func,func是B*类型,所以不构成多态【多态要求是父类指针/引用调用】
};
int main(int argc ,char* argv[])
{B*p = new B;p->func();//输出结果是B->0return 0;
}
//情况4:编译报错
class A
{
public:virtual void func(int val){ std::cout<<"A->"<< val <<std::endl;}//A没有缺省参数,会报错virtual void test(){ func();}
};
class B : public A
{
public:void func(int val=0){ std::cout<<"B->"<< val <<std::endl; }
};
int main(int argc ,char* argv[])
{B*p = new B;p->func();//编译报错return 0;
}
类的大小–虚函数表
单继承的虚表指针
先给出结论:
当父类定义了虚函数时,在子类进行继承的时候会将父类的虚函数表也给继承下来所以那一些虚函数在子类中也是virtual类型的,如果要对父类中的虚函数进行重写时或添加虚函数,顺序是:
- 先将父类的虚函数列表复制过来
- 重写虚函数时是把从父类继承过来的虚函数表中对应的虚函数进行相应的替换。
- 如果子类自己要添加自己的虚函数,则是把添加的虚函数加到从父类继承过来虚函数表的尾部。
注意:
- 严格说是同一个的类的不同对象都有各自的虚函数表,只是指向相同的虚函数,虚函数是共用的
- 子类和父类中的虚函数表中没重写的虚函数也是共用的,不是共有虚表哦!
先看一道笔试题
class Base
{
public:virtual void Func1(){cout << "Func1()" << endl;}
private:int _b = 1;
};
//sizeof(Base) = 8;
class Base
{
public:virtual void Func1(){cout << "Func1()" << endl;}
};
//sizeof(Base) = 4;
class Base
{
public:virtual void Func1(){cout << "Func1()" << endl;}
private:int _b = 1;char _c;//内存对齐
};
//sizeof(Base) = 12;
除了private成员,还多了一个__vfptr
放在对象的前面(注意有些平台可能会放到对象的最后面,这个跟平台有关),对象中的这个指针叫做虚函数表指针(v代表virtual,f代表function)。
一个含有虚函数的类中都至少都有一个虚函数表指针,因为该类内的虚函数的地址要被放到虚函数表中,虚函数表也简称虚表。本质是函数指针数组。不是虚函数就不会进虚基表。
虚函数表本质是一个存虚函数指针的指针数组,一般情况这个数组最后面放了一个nullptr
。【VS2013版本下是这样】
如何实现多态:当父类的指针或者引用指向父类对象时,对应的是父类对象的模型;当父类的指针或引用指向子类对象时,是子类对象的父类对象的切片【如果子类对象重写了虚函数,那么虚函数表会不一样】,以上这两种情况对应的对象模型是一样的,但是虚表不一定相同。多态实际是依靠虚表来实现的,里面虚函数的地址不一样。这里涉及的是动态绑定。
自己写一个代码访问虚表里的虚函数
class A
{
public:virtual void func1() { cout << "A::func1" << endl; }virtual void func2() { cout << "A::func2" << endl; }
private:int _a;
};class B: public A
{
public:virtual void func1() { cout << "B::func1" << endl; }virtual void func3() { cout << "B::func3" << endl; }void func4() { cout << "B::func4" << endl; }
private:int _b;
};typedef void(*VF_Ptr)();//类中的4个函数声明都是一样的,故可以typedef一样的
void PrintVFTable(VF_Ptr vft[])//传的是函数指针数组
{for (int i = 0; vft[i] != nullptr; i++){printf("[%d]:%p->", i, vft[i]);vft[i]();}
}int main()
{A a;B b;PrintVFTable((VF_Ptr*)(*((void**)&a)));//此代码在32/64位平台均可,void**解引用得到void*,那void*在不同平台大小也不一样,故可适应//只要是个二级指针就可以//把虚表打印出来PrintVFTable((VF_Ptr*)(*((int*)&a)));//仅适合32位平台--指针大小位4自己PrintVFTable((VF_Ptr*)(*((int*)&b)));
}
多继承的虚表指针
结论:
- 该类继承自几个不同对象就有多少个虚函数指针。
多继承派生类的未重写的虚函数放在第一个继承基类部分的虚函数表中
//访问第一张虚表
PrintfVFTable((VFPtr*)(*(void**)&d));
//访问第二张虚表
PrintfVFTable((VFPtr*)(*(void**)((char*)&d+sizeof(Base1))));
//访问第二张虚表
Base2* ptr = &d;
PrintfVFTable((VFPtr*)(*(void**)(ptr));
菱形继承的虚表指针
和多继承下的对象模型差不多,具体看图
菱形虚拟继承的虚表指针
最后继承的那个子类D要重写父类的虚函数,因为菱形虚拟继承只会有一份父类A,而B和C都重写了A中的虚函数,那D对象模型中的A的虚表就不知道应该放谁重写的虚函数,当D重写以后,A的虚表中放D重写的虚函数地址即可。
虚函数在哪?虚表在哪?
通过代码验证一下
int main()
{int a = 0;cout << "栈:" << &a << endl;//0083FBC0int* p = new int;cout << "堆:" << p << endl;//00CCA430const char* str = "aaa";cout << "代码段/常量区:" << (void*)str << endl;//00729B78static int b = 0;cout << "静态区/数据段:" << &b << endl;//0072C400A a;cout << "虚表:" << (void*)*((int*)&a) << endl;//00729B34return 0;
}
注意:上述地址每次运行都不一样。只需要看地址区间即可,可看到虚表是在代码段/常量区,在类对象里的是虚表指针。虚表存的是虚函数指针。虚函数和普通函数一样的,都是存在代码段的。
虚表对同一个类创建的多个对象而言,是共享的,就只有一份,所以在常量区。不同类的虚表不一样。
静态绑定和动态绑定
静态绑定又称为前期绑定(早绑定),在程序编译期间确定了程序的行为,也称为静态多态,比如:函数重载。编译时的多态性是通过函数重载和模板体实现的
动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体行为,调用具体的函数,也称为动态多态。根据指针指向的类型去调用具体的函数【父类对象本身或父类对象的切片==>虚函数表不一样】,运行时的多态性是通过虚函数实现的
题目
class A
{
public:A ():m_iVal(0){test();}virtual void func() { std::cout<<m_iVal<<‘ ’;}void test(){func();}
public:int m_iVal;
};class B : public A
{
public:B(){test();}virtual void func(){++m_iVal;std::cout<<m_iVal<<‘ ’;}
};int main(int argc ,char* argv[])
{A*p = new B;p->test();return 0;
}
//输出0 1 2
分析:new B时先调用父类A的构造函数,执行test()函数,再调用func()函数由于此时还处于对象构造阶段,多态机制还没有生效,所以,此时执行的func函数为父类的func函数,打印0构造完父类后执行子类构造函数,又调用test函数,然后又执行func()由于父类已经构造完毕,虚表已经生成,func满足多态的条件,所以调用子类的func函数,对成员m_iVal加1,进行打印,所以打印1,最终通过父类指针p->test(),也是执行子类的func,所以会增加m_iVal的值,最终打印2
class A
{
public: virtual void f(){cout<<"A::f()"<<endl;}
};
class B : public A
{
private:virtual void f(){cout<<"B::f()"<<endl;}
};
A* pa = (A*)new B;
pa->f();
//输出B::f()
分析:虽然子类函数为私有,但是多态仅仅是用子类函数的地址覆盖虚表,最终调用的位置不变,只是执行函数发生变化
相关文章:

C++之多态 虚函数表
多态 多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。 需要区分一下:1、菱形虚拟继承,是在继承方式前面加上virtual; class Person {}; class Student : virtual public Person {}; class Teacher…...

AI_Papers周刊:第四期
2023.02.28—2023.03.05 Top Papers Subjects: cs.CL 1.Language Is Not All You Need: Aligning Perception with Language Models 标题:KOSMOS-1:语言不是你所需要的全部:将感知与语言模型相结合 作者:Shaohan Huang, Li …...

A Simple Framework for Contrastive Learning of Visual Representations阅读笔记
论文地址:https://arxiv.org/pdf/2002.05709.pdf 目前流行的无监督学范式。通过训练,使模型拥有比较的能力。即,模型能够区别两个数据(instance)是否是相同的。这在 深度聚类 领域受到广泛的关注。(在有监…...

mac安装开发工具:clipy、iterm2、go、brew、mysql、redis、wget等
wget brew install wget clipy Releases Clipy/Clipy GitHub 环境变量 ~下有三个文件 .zshrc .zprofile .bash_profile > cat .zshrc export PATH$PATH:/usr/local/mysql/bin> cat .zprofile eval "$(/opt/homebrew/bin/brew shellenv)"> cat .bas…...

DJ1-1 计算机网络和因特网
目录 一、计算机网络 二、Interent 1. Internet 的介绍 2. Internet 的具体构成 3. Internet 提供的服务 4. Internet 的通信控制 一、计算机网络 定义:是指两台以上具有独立操作系统的计算机通过某些介质连接成的相互共享软硬件资源的集合体。 计算机网络向…...

[1.3.3]计算机系统概述——系统调用
文章目录第一章 计算机系统概述系统调用(一)什么是系统调用,有何作用(二)系统调用与库函数的区别(三)小例子:为什么系统调用是必须的(四)什么功能要用到系统调…...

【Java开发】JUC进阶 03:读写锁、阻塞队列、同步队列
1 读写锁(ReadWriteLock)📌 要点实现类:ReentrantReadWirteLock通过读写锁实现更细粒度的控制,当然通过Synchronized和Lock锁也能达到目的,不过他们会在写入和读取操作都给加锁,影响性能&#x…...

Fragment中获取Activity的一点点建议
平时的Android开发中,我们经常要在Fragment中去获取当前的Activity实例,刚开始的时候可能使用使用Fragment提供的getActivity方法来获取,但是这个方法可能返回null,为了让程序可以正常运行,项目中就出现大量下面这样的…...

Java Math类
Java Math 类是 Java 标准库中提供的一个数学计算类,它提供了很多数学函数,如三角函数、指数函数、对数函数等。在实际工作中,Java Math 类常常被用于处理数学计算问题,例如计算复杂的数学公式、实现数学算法等。本文将详细介绍 J…...

Javascript -- 加载时间线 正则表达式
js加载时间线 1、创建Document对象,开始解析web页面,解析html元素和他们的文本内容后添加Element对象和Text节点到文档中。这个阶段的document.readyState ‘loading’ 2、遇到link外部css,创建线程加载,并继续解析文档 3、遇到…...

gdb/git的基本使用
热爱编程的你,一定经常徘徊在写bug和改bug之间,调试器也一定是你随影而行的伙伴,离开了它你应该会寝食难安吧! 目录 gdb的使用 断点操作 运行调试 观察数据 Git的使用 仓库的创建和拉取 .gitignore “三板斧” 常用指令 gd…...

信息安全与数学基础-笔记-④二次同余方程
知识目录二次同余方程的解欧拉判别式Legendre (勒让德符号)二次同余方程的解 什么是二次同余方程的解 注意这里二次同余方程和一次同余方程是不一样的 在x2x^2x2 三 a (mod m) 方程中举例 ↓ 解即剩余类,因为是模m,所以我们在 [ 0, m-1 ]中逐个代入看是…...

Luogu P4447 [AHOI2018初中组]分组
题目链接:传送门 将nnn个可重复的整数分为mmm组,每组中的数必须连续且不重复,使人数最少的组人数最多。 两个最值肯定第一想到二分,每次二分出一个值,判断在这个值为答案的前提下能否完成分组。 在思考判别函数时发现…...

手把手创建flask项目
Flask 框架流程 什么是Flask: Flask诞生于2010年, 使用python语言基于Werkzeug工具箱编写的轻量级Web开发框架 Flask本身相当于一个内核, 其他几乎所有的功能都要用到扩展(邮件:Flask-Mail, 用户认证:Flask-Login, 数据库:Flask-SQLAlchemy). Flask的核心在于Werkz…...

SpringCloud-4_Eureka服务注册与发现
Eureka作为一个老牌经典的服务注册&发现技术,其设计和理念,也在影响后面的组件。目前主流的服务注册&发现的组件是Nacos当前项目架构问题分析-引出Eureka问题分析:1.在企业级项目中,服务消费访问请求会存在高并发2.如果只…...

【react全家桶】生命周期
文章目录04 【生命周期】1.简介2.初始化阶段2.1 constructor2.2 componentWillMount(即将废弃)2.3 static getDerivedStateFromProps(新钩子)2.4 render2.5 componentDidMount2.6 初始化阶段总结3.更新阶段3.1 componentWillRecei…...

虚拟机安装Windows 10
虚拟机安装Windows 10 镜像下载 方法一:下载我制作好的镜像文件->百度网盘链接 提取码:Chen 方法二:自己做一个 进入微软官网链接 下载"MediaCreationTool20H2" 运行该工具 点击下一步选择路径,等他下载好就欧克了…...

【CMU15-445数据库】bustub Project #2:B+ Tree(下)
Project 2 最后一篇,讲解 B 树并发控制的实现。说实话一开始博主以为这块内容不会很难(毕竟有 Project 1 一把大锁摆烂秒过的历史x),但实现起来才发现不用一把大锁真的极其痛苦,折腾了一周多才弄完。 本文分基础版算法…...

leetcode 困难 —— 外星文字典(拓扑排序)
题目: 现有一种使用英语字母的外星文语言,这门语言的字母顺序与英语顺序不同。 给定一个字符串列表 words ,作为这门语言的词典,words 中的字符串已经 按这门新语言的字母顺序进行了排序 。 请你根据该词典还原出此语言中已知的字…...

ubuntu server 18.04使用tensorflow进行ddqn训练全过程
0. 前言 需要使用ddqn完成某项任务,为了快速训练,使用带有GPU的服务器进行训练。记录下整个过程,以及遇到的坑。 1. 选择模板代码 参考代码来源 GitHub 该代码最后一次更新是Mar 24, 2020。 环境配置: python3.8 运行安装脚本…...

2023年全国最新二级建造师精选真题及答案14
百分百题库提供二级建造师考试试题、二建考试预测题、二级建造师考试真题、二建证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 二、多选题 61.已经取得下列资质的设计单位,可以直接申请相应类别施工总承包一级…...

mysql一条语句的写入原理
mysql写入原理 我们知道在mysql数据库最核心的大脑就是执行引擎; 其中的默认引擎Innodb在可靠执行和性能中做出来平衡; innodb支持在事务控制、读写效率,多用户并发,索引搜索方面都表现不俗; innodb如何进行数据写入…...

嵌入式Linux内核代码风格(二)
第九章:你已经把事情弄糟了 这没什么,我们都是这样。可能你的使用了很长时间Unix的朋友已经告诉你“GNU emacs”能 自动帮你格式化C源代码,而且你也注意到了,确实是这样,不过它所使用的默认值和我们 想要的相去甚远&a…...

Spring Boot @Aspect 切面编程实现访问请求日志记录
aop切面编程想必大家都不陌生了,aspect可以很方便开发人员对请求指定拦截层,一般是根据条件切入到controller控制层,做一些鉴权、分析注解、获取类名方法名参数、记录操作日志等。 在SpringBoot中使用aop首先是要导入依赖如下: …...

初学者的第一个Linux驱动
软件环境:Ubuntu20.04 Linux内核源码:3.4.39 硬件环境:GEC6818 什么是驱动?简单来说就是让硬件工作起来的程序代码。 Linux驱动模块加载有两种方式: 1、把写好的驱动代码直接编译进内核。 2、把写好的驱动代码编…...

7. 拼数
1 题目描述 拼数成绩10开启时间2021年09月24日 星期五 18:00折扣0.8折扣时间2021年11月15日 星期一 00:00允许迟交否关闭时间2021年11月23日 星期二 00:00 设有 n个正整数 a[1]…a[n],将它们联接成一排,相邻数字首尾相接,组成一个最大的整…...

Java每天15道面试题 | Redis
redis 和 和 memcached 什么区别?为什么高并发下有时单线程的 redis 比多线程的memcached 效率要高? 区别: 1.mc 可缓存图片和视频。rd 支持除 k/v 更多的数据结构; 2.rd 可以使用虚拟内存,rd 可持久化和 aof 灾难恢复࿰…...

13_pinctrl子系统
总结 pinctrl作为驱动 iomuxc节点在设备树里面 存储全部所需的引脚配置信息 iomux节点匹配pinctrl子系统 控制硬件外设的时候 要知道有哪些gpio 再看gpio有哪些服用寄存器 接着在程序配置gpio相关寄存器 这样搞效率很低 所以用iomux节点保存所有的引脚组 pinctrl驱动起来的时…...

Linux系统对于实施人员的价值
Linux系统对于实施人员的价值 随着互联网的发展,linux系统越来越突显了巨大的作用,很多互联网公司,政府企业,只要用到服务器的地方几乎都能看到linux系统的身影,可以说服务是不是在linux系统跑的代表了企业的技术水平&…...

ForkJoin 和 Stream并行流
还在用 for 循环计算两个数之间所有数的和吗?下面提供两种新方法! 1. ForkJoin 1.1 背景 要知道,在一个方法中,如果没有做特殊的处理,那么在方法开始到结束使用的都是同一个线程,无论你的业务有多复杂 那…...