C++期末复习总结(2)

目录

1.运算符重载

2.四种运算符重载

(1)关系运算符的重载

(2) 左移运算符的重载

(3)下标运算符的重载

 (4)赋值运算符的重载

3.继承的方式

4.继承的对象模型

5.基类的构造

6.名字遮蔽和类作用域

7.类继承的特殊关系

8.多态和虚函数


1.运算符重载

(1)其实这个知识我们并不是很陌生,我们在C语言学习阶段,就知道了*这个运算符,在我们学习基本的运算的时候,这个运算符就是用来计算乘法的,但是后来我们学到了指针之后,这个运算符就用来表示对于一个指针变量的解引用,这个时候我们就已经认识到了一个运算符的重载功能;

(2)我们通过下面这个实际的场景认识一下什么是c++里面的运算符重载,我们下面的这个代码场景是要为这个超女的分数上面加上30分,这个时候如果我们直接拿这个对象和数字相加,编译器是肯定不会通过的,因为这个编译器不知道要把这个数据加到那个成员变量上面去;

(3)针对这个问题,我们有两种解决方案,第一种就是设置一个函数,实现这个加分的功能,指定这个分数加到那个成员变量上面去,我们原本初始化这个分数是90,加上30分之后这个分数就变成了120分;

#include<string>
using namespace std;
class cgril
{friend void addscore(cgril& g, int score);
private:int m_xw;//超女的行为int m_score;//超女的分数
public:string m_name;//超女的姓名cgril(){m_xw = 60;m_name = "张三";m_score = 90;}void show(){cout << "行为:" << m_xw << "分数:" << m_score << "姓名:" << m_name << endl;}
};
void addscore(cgril& g, int score)//利用函数,实现加分的功能
{g.m_score = g.m_score + score;
}
int main()
{//导演的要求就是,每轮表演之后,加上对应的得分cgril g;addscore(g, 30);g.show();return 0;
}

(4)上面的这个写法偏向于C的写法,接下来我们看一下如何使用C++写法实现这个加分的功能,就是把这个函数的名字修改为operator+即可,这个operator是关键字,+就是我们想要重载的运算符 ;

(5)上面的这个运算符重载的基本写法,实际上这个运算符的重载既可以写作成员函数,也可以写作全局函数,当我们实现一个类和一个整形数据加法的时候,如果我们写在成员函数里面,就可以只写一个参数,最后的返回值是*this,这个时候写法是这样的;

	cgril& operator+(int score)//利用函数,实现加分的功能{m_score = m_score + score;return *this;}
};
int main()
{//导演的要求就是,每轮表演之后,加上对应的得分cgril g;g = g + 30;g.show();return 0;
}

这个时候,那个对象调用这个成员函数,那个对象就是this指针,这样写在成员函数里面,我们就不需要写这个友元函数了,因为这个在类的里面,我们是可以对于这个私有的成员变量直接进行使用,这个时候g=g+30我们需要把这个返回值设置为这个类的引用类型;

(6)当这个函数写在全局里面时候,有几个操作数,我们就需要写几个操作数,而且这个操作数的数据类型和我们使用的数据类型之间应该是一一对应的,例如我们想要实现这个cgril+int,我们在使用这个加法运算符的时候,我们就必须把这个类写在左边,int类型的数据写在右边,这个顺序是不可以改变的;

(7)下面的这些运算符重载的时候必须写在这个成员函数里面去:赋值运算符=    函数调用运算符( )   下标运算符[  ]      以及这个指针访问成员操作符->   ;

2.四种运算符重载

(1)关系运算符的重载

关系运算符就是我们常说的这个大于小于和等于这些符号的比较,我们对于两个类之间的比较,需要自己进行运算符的重载;

下面的就是重载了等于号大于号和小于号的运算符重载代码;

class student
{string m_name;int m_cj;//学生成绩int m_bx;//学生的表现int m_td;//学生的学习态度
public:student(string name, int cj, int bx, int td){m_name = name;m_cj = cj;m_bx = bx;m_td = td;}bool operator==(const student& s){if (m_cj + m_bx + m_td == s.m_cj + s.m_bx + s.m_td){return true;}else{return false;}}bool operator<(const student& s){if (m_cj + m_bx + m_td < s.m_cj + s.m_bx + s.m_td){return true;}else{return false;}}bool operator>(const student& s){if (m_cj + m_bx + m_td > s.m_cj + s.m_bx + s.m_td){return true;}else{return false;}}
};
int main()
{student s1("张三", 80, 20, 70);student s2("李四", 70, 70, 30);if (s1 == s2){cout << "张三和李四的分数一样" << endl;}else{if (s1 < s2){cout << "张三比李四的分数低" << endl;}else{cout << "张三比李四的分数高" << endl;}}return 0;
}

(2) 左移运算符的重载

这个cout有15种重载,因此可以输出各种数据类型的数据,但是cout无法输出我们自己定义的类和对象,这个时候就需要我们对于其进行重载,cout这个对象的返回值实际上就是一个ostream类型的,这个如果是全局函数,就需要两个参数,一个就是cout对象,一个就是我们的自定义类型的对象,如果是成员函数的话,,就只需要一个参数,因为对象本身是隐式传递的,不能出现在形参列表里面;

using namespace std;
class student
{friend ostream& operator<<(ostream& cout, const student& s);int m_mark;string m_name;
public:student(){m_mark = 90;m_name = "张三";}void show(){cout << "这个同学的姓名是" << m_name << "成绩是:" << m_mark << endl;}
};
ostream& operator<<(ostream& cout, const student& s)
{cout << "姓名:" << s.m_name << "  分数:" << s.m_mark << endl;return cout;
}
int main()
{student s1;cout << s1 << endl;return 0;
}

成员函数版本的运算符重载:

#include<string>
using namespace std;
class student
{//friend ostream& operator<<(ostream& cout, const student& s);int m_mark;string m_name;
public:student(){m_mark = 90;m_name = "张三";}void show(){cout << "这个同学的姓名是" << m_name << "成绩是:" << m_mark << endl;}ostream& operator<<(ostream& cout){cout << "姓名:" << this->m_name << "  分数:" << this->m_mark << endl;return cout;}
};
int main()
{student s1;s1 << cout << endl;return 0;
}

 我们可以理解为这个运算符左右两边一共有两个操作数,这个时候我们的自定义类型作为一个隐藏的参数,所以对应的主函数里面这个自定义对象和cout对象的位置需要被改变;

这个时候cout在右边,不是我们想要的结果,因此这个左移运算符的重载,只能写成这个全局函数,不能写成成员函数;

(3)下标运算符的重载

如果没有重载下标运算符,如果我们想要查看这个数组元素,我们就需要自己定义函数,使用这个小括号加上下标的方式表示,但是我们知道这个访问操作符就是中括号,因此下面我们介绍小标访问运算符的重载;

#include<iostream>
#include<string>
using namespace std;
class student
{
private:string m_zy[3];
public:student(){m_zy[0] = "父母";m_zy[1] = "老师";m_zy[2] = "朋友";}void show(){cout << m_zy[0] << "  " << m_zy[1] << "  " << m_zy[2] << "  " << endl;}string& operator[](int ii){return m_zy[ii];}
};
int main()
{student s1;s1[2] = "知己";cout << "第三亲密:" << s1[2] << endl;s1.show();return 0;
}

实际在开发的过程中,我们需要有两个版本的重载函数,一个版本是可以对于我们的数据进行修改的,另外的一个就是针对常变量只能调用常函数;

#include<iostream>
#include<string>
using namespace std;
class student
{
private:string m_zy[3];
public:student(){m_zy[0] = "父母";m_zy[1] = "老师";m_zy[2] = "朋友";}void show(){cout << m_zy[0] << "  " << m_zy[1] << "  " << m_zy[2] << "  " << endl;}string& operator[](int ii){return m_zy[ii];}const string& operator[](int ii) const{return m_zy[ii];}
};
int main()
{student s1;s1[2] = "知己";cout << "第三亲密:" << s1[2] << endl;s1.show();const student s2 = s1;cout << "第三亲密:" << s2[2] << endl;return 0;
}

 (4)赋值运算符的重载

赋值运算符其实编译器会提供默认的,我们了解即可,这个我们在重载赋值运算符的时候,需要判断这个时不时会出现自己给自己赋值的情况,这个是合法的,我们直接返回this解引用即可;this就是我们想要赋值的对象;

编译器默认提供的赋值构造函数是浅拷贝,如果这个不存在动态开辟空间,就可以满足需求,否则的话就需要我们自己实现深拷贝;

#include<iostream>
#include<string>
using namespace std;
class student
{
public:string m_name;int m_score;void show(){cout << "姓名:" << m_name << "    年龄:" << m_score << endl;}student& operator=(const student& s){if (this == &s)return *this;else{m_name = s.m_name;m_score = s.m_score;}return *this;}
};
int main()
{student s1;s1.m_name = "张三";s1.m_score = 100;s1.show();student s2;s2 = s1;s2.show();return 0;
}

3.继承的方式

(1)三种不同的继承方式

上面展示的就是三种不同的继承方式,我们假设这个基类有三个成员变量,一个是共有的,一个是受保护的,一个是私有的,经过不同的继承方式之后,这个成员变量的类型会发生什么变化;

第一种就是公有继承,公有继承的时候,我们的父类里面的公有成员还是公有成员,受保护的成员还是受保护的成员,私有成员就不存在了;

第二种是受保护的继承,这个时候,原来的公有成员就变成了受保护的成员,原来的父类里面的受保护的成员还是受保护的,原来的私有成员变量这个时候还是不存在的;

第三种就是私有的继承,这个时候,原来的父类里面的共有的成员变量和保护的成员变量就是私有的了,原来的父类里面的受保护的成员变量也是不存在的;

(2)我们在这个继承的子类里面是没有办法访问这个所谓的父类里面的私有成员变量的,但是如果我们想要在这个子类里面去访问这个私有的成员变量,可以在父类里面添加共有的函数访问这个私有的成员变量,这个时候我们就可以直接调用这个函数访问父类里面的私有的成员变量;

就像下面的展示那样,我们在子类里面本来是没有办法去访问父类的私有成员变量的,但是我们可以在父类里面创建共有的成员函数,这样在子类里面,我们就可以通过调用这个函数达到间接访问了父类的私有成员变量的目的;

class comers
{
private:int m_aa;
public:void func(){cout << m_aa << endl;}
};
class comerss :public comers
{
private:int m_bb;
public:void show(){func();}
};
int main()
{comerss c1;c1.show();return 0;
}

(3)我们可以使用using 关键字改变父类的成员变量的访问权限,例如我们可以把这个共有的改变成为受保护的,把这个受保护的改变权限为共有的,这个父类里面的私有的成员变量的权限是没有办法通过这个关键字改变的,因为这个父类里面的私有的成员变量在这个子类里面根本就不会存在,因此这个关键字只对于public权限和protected权限发挥作用;

class a
{
public:int m_a;
protected:int m_b;
private:int m_c;
};
class b :public a
{
public:using a::m_b;
protected:using a::m_a;
};
int main()
{	b bb1;return 0;
}

通过上面的这个具体的实例,我们就可以把这个父类里面的公有成员变量修改为受保护的,把这个受保护的成员变量修改权限为公有的,当然也可以把他们的权限设置为私有的;

4.继承的对象模型

(1)这个地方是帮助我们了解C++继承语法的底层逻辑,而不是学懂这个底层逻辑,我们只是了解,这样就可以让我们更好理解前面的一些原因;

(2)第一点就是基类在写这个构造函数的时候,会先运行这个父类的构造函数,再去运行这个基类的构造函数,这个我们可以进行尝试,当我们创建两个类,假设是A类和B类,如果A是父类,B是子类,我们把这个A类里面的构造函数设置为私有的,这个时候我们在B这个子类里面去写构造函数就会报错,原因就是我们上面提及到的我们在执行子类的构造函数的时候,会先执行父类的构造函数,这个也是为什么我们建议把这个函数写为共有的,成员变量写为私有的,这个时候我们学习了继承,就可以更好地进行理解;

(3)销毁子类对象的时候,会先执行子类的析构函数,再去执行父类的析构函数,这个和构造函数的执行顺序是恰好相反的;

(4)创建派生类对象的时候,只申请了一次这个内存,申请的内存空间的大小就是基类加上派生类的内存的和,先调用基类的构造函数,初始化基类,再调用派生类的构造函数,初始化派生类,在基类和派生类的构造函数里面,this指针是相同的地址,派生类和基类都有的成员变量的地址也是一样的;

(5)在C++里面这个成员变量的访问权限只是语法上面的限制,我们可以使用memset函数清零数据,包括这个私有的成员变量,即使这个私有的成员变量在类的外面不能被访问;我们可以使用指针突破这个访问权限的限制,所以这个访问权限只是语法上面的一个解释罢了;

5.基类的构造

(1)我们可以使用初始化列表的方式指定要使用的基类的构造函数类型,因为我们前面提及过,这个创建子类也就是派生类的对象的时候,需要先去调用这个父类的构造函数,这个时候如果父类里面有多个构造函数,我们就可以使用初始化列表的方式指定调用基类里面的哪个构造函数;

(2)我们在创建派生类的对象的时候,是使用基类初始化这个基类的成员变量,派生类初始化派生类的成员变量,你可能会问,这些基类的成员变量都被派生类给继承了,为什么不使用派生类初始化基类的成员变量,这个有两点原因;

第一就是我们的基类里面的私有的成员变量我们是无法在这个派生类里面看到的,更别说去对于这个变量进行初始化了;

第二就是这个如果我们在这个派生类里面对于这个基类的成员变量进行初始化,如果这个基类有很多个派生类,我们的这个代码就显得很冗余,而且这个派生类存在的意义就是减少这个相同的成员变量的书写带来的麻烦,这样搞得话就不符合这个逻辑了;

(3)下面的就是我们定义了一个派生类和一个基类,通过初始化列表的方式,确定这个派生类调用的是基类里面的哪个构造函数;

class a
{
public:int m_a;
private:int m_b;
public:a():m_a(0), m_b(0){cout << "调用了基类的构造函数" << endl;}a(int aa, int bb):m_a(aa), m_b(bb){cout << "调用了含有两个参数的构造函数" << endl;}a(const a& aa):m_a(aa.m_a + 1), m_b(aa.m_b + 1){cout << "调用了基类的拷贝构造函数" << endl;}void showa(){cout << "m_a数值大小:" << m_a << "m_b的数值大小" << m_b << endl;}
};
class b :public a
{
public:int m_c;b():m_c(0),a(){cout << "调用了这个派生类的构造函数" << endl;}b(int a, int b, int c):a(a, b), m_c(c){cout << "调用派生类的构造函数b(int a, int b, int c)" << endl;}b(const a& aa, int c):a(aa), m_c(c){cout << "调用派生类的拷贝构造函数" << endl;}void showb(){cout << "m_c数值大小:" << m_c << endl;}
};
int main()
{b b1;b1.showa();b1.showb();cout << endl;b b2(1, 2, 3);b2.showa();b2.showb();cout << endl;a a1(10, 20);b b11(a1, 30);return 0;
}

我们分别使用初始化列表的方式指定了调用默认的构造函数,调用含有多个参数的构造函数,以及这个拷贝构造函数;子类里面的第二个初始化列表我们使用的是这个基类的含有两个参数的构造函数进行初始化的,第三个初始化列表是使用基类里面的拷贝构造函数进行初始化的;

6.名字遮蔽和类作用域

(1)下面就是定义了一个基类和一个子类,我们创建了一个子类的对象,这个基类和子类的这个成员变量的名字以及这个成员函数的名字都是一样的,这个时候我们的打印结果就是基类的成员变量和成员函数;

using namespace std;
class a
{
public:int m_a = 20;void show(){cout << "调用了基类的函数" << endl;}
};
class b :public a
{
public:int m_a = 30;void show(){cout << "调用了派生类的函数" << endl;}
};
int main()
{b b1;cout << "b1对象的m_a的值是:" << b1.m_a << endl;b1.show();return 0;
}

(2)当基类的函数名和这个派生类里面的函数名字相同的时候,因为这个是继承,所以派生类里面就会隐含的包括了这个基类的成员变量和成员函数,名字相同的时候,派生类的函数就会把这个基类里面函数覆盖掉;

using namespace std;
class a
{
public:int m_a = 20;void show(){cout << "调用了基类的函数" << endl;}void func(int a){cout << "调用了这个函数" << endl;}
};
class b :public a
{
public:int m_a = 30;//void func() { cout << "调用了派生类的函数" << endl; }
};
int main()
{b b1;cout << "b1对象的m_a的值是:" << b1.m_a << endl;b1.show();b1.func(1);
}

例如上面的这个程序,两个相同的函数func,如果我们把这个继承类里面的func函数放开,这个时候运行就会报错,因为这个时候父类的func函数会被覆盖掉,我们传递参数是不合语法的,但是我们把这个注释掉之后,就可以运行成功,因为这个时候,不存在函数名字相同的情况,我们就可以直接调用这个子类里面的有一个参数的func函数了,实际上这个成员函数在子类里面也是存在的,只要不重名,这个基类里面的这个函数就不会被覆盖掉;

实际上这个名字遮蔽就是一个表象,类作用域才是实质,因为实际上当存在继承关系的时候,这个基类的作用域是嵌套在这个派生类里面的,我们一般会在这个派生类里面去寻找,只有这个在派生类里面找不到的时候,才回到基类里面去寻找;

7.类继承的特殊关系

(1)如果我们使用派生类的对象赋值给基类的对象(包括私有成员),但是这个时候会舍弃掉非基类成员:

下面这个代码里面,我们对于这个b1对象进行操作,最后把他赋值给a1这个对象,这个时候我们会发现a1这个对象里面的私有成员m_b也会被更新的,也就是说即使是私有的成员变量,也是会被赋值的;

class a
{
public:int m_a = 0;
private:int m_b = 0;
public:void show(){cout << "m_a:" << m_a << "   m_b:" << m_b << endl;}void setb(int b){m_b = b;}
};
class b :public a
{
public:int m_c = 0;void show(){cout << "m_a:" << m_a << "   m_c:" << m_c << endl;}
};
int main()
{a a1;b b1;b1.m_a = 10;b1.setb(20);b1.m_c = 30;a1.show();a1 = b1;a1.show();return 0;
}

(2)基类的指针可以不经过显示转换指向派生类的对象,因为基类和派生类有特殊的关系,他们的内存模型是一样的,所以使用基类的指针执行派生类,没有问题;

还是上面得继承关系,我们定义基类的指针指向派生类的对象:

int main()
{b b1;a* a1 = &b1;b1.m_a = 10;b1.setb(20);b1.m_c = 30;b1.show();a1->m_a = 10;a1->setb(20);a1->show();return 0;
}

8.多态和虚函数

(1)什么是多态?

多态就是我们定义了两个类之间的继承关系,定义了基类的指针pa,指向的是派生类的对象g,这个时候我们使用这个指针去调用函数,就只能调用基类的构造函数,因为这个指针就是基类的;

我们在这个基类的成员函数show前面加上virtual关键字,就可以使用这个执行派生类对象的指针去访问这个派生类的函数,即使这个类是基类的,我们也是可以访问到这个派生类的成员函数的;

因为这个是函数前面加上virtual关键字,我们把这个函数叫做虚函数,有了虚函数之后,基类的指针指向基类对象就会调用基类的成员变量和函数,指向派生类的对象之后就会调用派生类的成员变量和函数,基类的指针表现出来多种形态,我们把这个现象叫做多态;

class allcomer
{
public:int m_bh;void show(){cout << "class allcomer我的编号是:" << m_bh << endl;}
};
class cgril :public allcomer
{
public:int m_age;void show(){cout << "class cgril :public allcomer我的年龄是" << m_age << endl;}
};
int main()
{cgril g;g.m_bh = 8;g.m_age = 18;g.show();allcomer* pa = &g;pa->show();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/24892.shtml

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

相关文章

易飞销货单出货时审核库存检查

公司接到一客户因品种多而数量少&#xff0c;单一出货计划行比较多&#xff0c;而只上了生产ERP易飞&#xff0c;审核时经常会出现倒催货&#xff0c;提前做销售单&#xff0c;行数有时超30行以上&#xff0c;审核跳窗报错时也不方便查找&#xff0c;特写一外挂程序&#xff0c…

How to: Build a Custom End-User Skin Selector

This section explains how to populate a ComboBoxEdit control with DevExpress skin items. 本节介绍如何使用DevExpress皮肤项填充ComboBoxEdit控件。 To populate a combo box editor, iterate through the SkinManager.Skins collection, which returns all currently a…

【c语言】自定义类型----结构体

结构体是c语言的一种自定义类型&#xff0c;自定义类型对于开发者及其重要的类型&#xff0c;它可以随意由开发者进行谱写功能&#xff0c;而今天的结构体可以用来表示一种变量的单个或多种具体属性&#xff0c;再编写代码时有着不可替代的作用&#xff01;&#xff01;&#x…

一个简单的消息队列

目录 原理 实现代码 示例 原理 消息队列是一个先进先出栈&#xff0c;每次都处理第一项&#xff0c;处理完了过后会删除这个消息&#xff0c;这是一个简单的消息队列图&#xff1a; 实现代码 首先消息队列需要一个队列&#xff0c;我们用Python里的列表&#xff1a; self.…

常见的api: BigInteger

一.获取一个大的随机整数 1.代码: BigInteger bd1 new BigInteger(4, new Random());System.out.println(bd1); 2.打印的结果:2 3.注释获取的是0-16之间的随机整数 二.获取一个指定的大的数 1.代码&#xff1a; BigInteger bd2 new BigInteger("100");System.o…

人工智能--教育领域的运用

文章目录 &#x1f40b;引言 &#x1f40b;个性化学习 &#x1f988;体现&#xff1a; &#x1f988;技术解析&#xff1a; &#x1f40b;智能辅导与虚拟助手 &#x1f988;体现&#xff1a; &#x1f988;技术解析&#xff1a; &#x1f40b;自动评分与评估 &#x1f…

植物大战僵尸杂交版最新2.0.88手机+电脑+苹果+修改器

在这个充满奇妙的平行宇宙中&#xff0c;植物和僵尸竟然能够和谐共存&#xff01;是的&#xff0c;你没听错&#xff01;一次意外的实验&#xff0c;让这两个看似对立的生物种类发生了基因杂交&#xff0c;创造出了全新的生物种类——它们既能够进行光合作用&#xff0c;也具备…

2024年【R2移动式压力容器充装】考试技巧及R2移动式压力容器充装复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 R2移动式压力容器充装考试技巧参考答案及R2移动式压力容器充装考试试题解析是安全生产模拟考试一点通题库老师及R2移动式压力容器充装操作证已考过的学员汇总&#xff0c;相对有效帮助R2移动式压力容器充装复审考试学…

Linux 35.5 + JetPack v5.1.3@RACER编译安装

Linux 35.5 JetPack v5.1.3RACER编译安装 1. 源由2. 编译&安装Step 1&#xff1a;依赖库安装Step 2&#xff1a;LKH-3安装Step 3&#xff1a;建立工程Step 4&#xff1a;编译工程Step 5&#xff1a;安装工程 3. 问题汇总3.1 组件ros-noetic-multi-map-server问题3.2 swarm…

记录:linux桌面管理基础-X11协议(X window system)

1、认识X11 X11是X协议&#xff0c;版本号为11。X协议是专门被设计为linux桌面管理服务的&#xff0c;而linux桌面环境不像windows那样作为系统内核的一部分&#xff0c;作为一个普通程序运行在用户态上。该协议的设计初衷是为了linux的图形界面满足跨平台、跨网络、与具体硬件…

DOM型xss靶场实验

DOM型xss可以使用js去控制标签中的内容。 我使用的是一个在线的dom型xss平台&#xff0c;靶场链接&#xff1a;Challenges 第一关Ma Spaghet!&#xff1a; Ma Spaghet! 关卡 <h2 id"spaghet"></h2> <script>spaghet.innerHTML (new URL(locatio…

【TB作品】msp430f5529单片机,dht22,温湿度传感器,OLED显示屏

使用DHT22温湿度传感器和OLED显示屏的单片机项目 博客名称 利用MSP430单片机读取DHT22并显示温湿度 作品功能 本项目利用MSP430单片机读取DHT22温湿度传感器的数据&#xff0c;并将温湿度信息显示在OLED显示屏上。通过这个项目&#xff0c;您可以学习如何使用单片机与传感器…

前端开发之中svg图标的使用和实例

svg图标的使用和实例 前言效果图1、安装插件2、vue3中使用2.1、 在components文件夹中,创建公共类SvgIcon/index.vue2.2、创建icons文件,存放svg图标和将所有的svg图标进行引用并注册成全局组件2.3、在man.js 中注册2.4、在vue.config.js中配置svg2.5、在vue中的调用svg图标3…

数仓建模—指标体系指标拆解和选取

数仓建模—指标拆解和选取 第一节指标体系初识介绍了什么是指标体系 第二节指标体系分类分级和评价管理介绍了指标体系管理相关的,也就是指标体系的分级分类 这一节我们看一下指标体系的拆解和指标选取,这里我们先说指标选取,其实在整个企业的数字化建设过程中我们其实最…

电脑下载速度很慢怎么解决 电脑下载加速工具测评推荐

电脑下载速度慢&#xff0c;不仅耗时冗长&#xff0c;还会影响工作和学习效率。漫长的等待让人心情焦虑&#xff0c;每一秒都是对耐心的极大考验。有关电脑下载速度很慢怎么解决&#xff0c;电脑下载加速工具评测推荐的问题&#xff0c;本文将进行详细介绍。 一、电脑下载速度…

IO进程线程(七)代码替换函数、守护进程

文章目录 一、代码替换函数&#xff08;一&#xff09;system函数&#xff08;二&#xff09;exec函数族 二、守护进程&#xff08;一&#xff09;创建1. 脱离父进程影响2. 脱离原会话组和进程组的影响3.修改进程工作目录4. 修改进程创建文件的掩码5. 关闭从父进程继承的文件描…

每日一练——相同分数的最大操作数目

3038. 相同分数的最大操作数目 I - 力扣&#xff08;LeetCode&#xff09;相同分数的最大操作数目 I3038. 相同分数的最大操作数目 I - 力扣&#xff08;LeetCode&#xff09; 第一版 int maxOperations(int* nums, int numsSize) {if(numsSize < 1)return 0;int temp 0;…

内存管理--4.用幻灯片讲解内存分配器Allocator

用幻灯片讲解内存分配器Allocators Allocators 内存分配器 提供内存分配策略的通用接口委托给 C 运行时&#xff1a;new / delete使用块内存池管理内存使用不同大小的块内存池管理内存 为什么用分配器? 将容器逻辑与内存分配策略解耦速度&#xff1a;内存分配速度慢确保…

基于51单片机水塔水位控制系统

基于51单片机水塔水位控制 &#xff08;仿真&#xff0b;程序&#xff09; 功能介绍 具体功能&#xff1a; 1.用滑动变阻器模拟水位&#xff0c;ADC0809将模拟信号转换为数字信号&#xff1b; 2.LCD1602显示当前水位和水位阈值&#xff1b; 3.当水位超过设定阈值&#xff…

MySQL基础_10.约束

文章目录 第一章、约束1.1 约束的定义1.2 非空约束1.3 唯一性约束1.4 主键约束1.5 自增列1.6 外键约束1.7 CHECK约束1.8 DEFAULT约束 第一章、约束 1.1 约束的定义 约束是对表中字段的限制。 约束按照作用范围可以分为&#xff1a;列级约束和表级约束 列级约束&#xff1a;声…