C++ 提高编程

1. 模板

1.1 模板的概念

1.2 函数模板

1.C++另一种编程思想称为 泛型编程,主要利用的技术就是模板
2.C++提供两种模板机制: 函数模板 和 类模板

1.2.1 函数模板语法

函数模板作用:建立一个通用函数,其函数返回值类型和形参类型可以不具体确定,用一个虚拟的类型来代表。

//语法
//函数声明或定义
template<typename T>

解释:
template – 声明创建模板
typename — 表明其后面的符号是一种数据类型,可以用class代替
T ---- 通用的数据类型,,名称可以替换,通常为大写字母。

#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//函数模板
//两个整形交互
void swapInt(int &a,int &b){int t = a;a = b;b = t;
} 
//两个浮点型交互
void swapDou(double &a,double &b){double t = a;a = b;b = t;
}
//函数模板
template<typename T>	//声明一个模板,告诉编译器后面代码中紧跟的T不要报错,T是一个通用数据类型
void mySwap(T &a,T &b){T tmp = a;a = b;b = tmp;
} 
int main() {int a=1,b=2;//1.自动推导类型 mySwap(a,b);//2.显示指定类型 mySwap<int>(a,b); return 0;
}    

在这里插入图片描述

1.2.2 函数模板注意事项

注意事项:
1.自动类型推导,必须推导出一致的数据类型T,才可以使用
2.模板必须要确定出T的数据类型,才可以使用

#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//函数模板注意事项 
template<typename T>	//typename可以替换为class没有区别 
//1.自动类型推导,必须推导出一致的数据类型T,才可以使用
void mySwap(T &a,T &b){T tmp = a;a = b;b = tmp;
}
void test01(){int a = 10;int b = 20;mySwap(a,b);/*char c = 'c';mySwap(a,c);//错误 推导不出一致的T类型 */cout<<a<<"-"<<b<<endl;
} 
//2.模板必须要确定出T的数据类型,才可以使用
template<class T>
void func(){cout<<"调用func"<<endl; 
}
void test02(){//无法调用 //func();//确定T的类型,可以调用func<int>(); 
}
int main() {int a=1,b=2;//1.自动推导类型 mySwap(a,b);//2.显示指定类型 mySwap<int>(a,b); return 0;
}    

1.2.3 函数模板案例

在这里插入图片描述

#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//实现通用 对数组进行排序的函数
//规则 从大到小
//算法 选择排序
//测试 char 数组,int 数组
template<class T>
void mySwap(T &a,T &b){T tmp = a;a = b;b =tmp;
} 
//排序算法--选择排序 
template<class T>
void mySort(T arr[],int len){for(int i=0;i<len;i++){int max = i;	//认定最大值下标for(int j=i+1;j<len;j++){//认定的最大值比遍历的最大值小,说明j下标元素才是真正的最大值 if(arr[max] < arr[j]){max = j;}} if(max != i){//交换max和i元素mySwap(arr[max],arr[i]);}}
} 
//打印数组模板
template<class T>
void printArr(T arr[],int len){for(int i=0;i<len;i++){cout<<arr[i]<<" ";}cout<<endl;
} 
void test01(){//测试char数组char chaArr[] = "badcfe"; int num = sizeof(chaArr) / sizeof(char);mySort(chaArr,num);printArr(chaArr,num);
} 
void test02(){int intArr[] = {7,5,1,5,8,9};int num = sizeof(intArr) / sizeof(int);mySort(intArr,num);printArr(intArr,num);
}
int main() {test01();test02();return 0;
}    

1.2.4 普通函数与函数模板的区别

在这里插入图片描述

#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//普通函数与函数模板区别//1.普通函数 调用可以发生隐式类型转换
//2.函数模板 用自动类型推导,不可以发生隐式类型转换
//3.函数模板 用显示指定类型,可以发生隐式类型转换 //普通函数
int myAdd01(int a,int b){return a+b;
} //函数模板
template<class T>
T myAdd02(T a,T b){return a+b;
} void test01(){//普通函数 int a=2,b=3;char c = 'c';cout<<myAdd01(a,b)<<endl;	//正常 //发生隐式转换 cout<<myAdd01(a,c)<<endl;	//正常-隐式转换 //模板函数cout<<myAdd01(a,b)<<endl;	//正常 cout<<myAdd01(a,c)<<endl;	//出错 //显示指定类型cout<<myAdd01<int>(a,c)<<endl;	//正常-可以隐式转换 
}
int main() {test01();test02();return 0;
}    

总结:建议使用显式指定方式,调用函数模板,因为自己可以确定通用类型T。

1.2.5 普通函数与函数模板调用规则

在这里插入图片描述

#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//普通函数与函数模板调用规则 //1.若函数模板和普通函数都可调用,则优先调普通函数 
//2.可以通过空模板参数列表 强制调用 函数模板 
//3.函数模板 可以发生 函数重载
//4.若函数模板可以产生更好的匹配,优先调用函数模板 void myPrint(int a,int b)
{cout<<"调用的是普通函数"<<endl; 
}
template<class T>
void myPrint(T a,T b){cout<<"调用的是模板函数"<<endl; 
}
template<class T>
void myPrint(T a,T b,T c){cout<<"调用的是重载的模板函数"<<endl; 
}
void test01(){int a=2,b=4;//调用的是 普通函数 myPrint(a,b);//通过空参数列表,强制调用函数模板myPrint<>(a,b);//函数模板重载 myPrint<>(a,b,100);//若函数模板可以产生更好的匹配,优先调用函数模板 char c1='a',c2='b';myPrint(c1,c2);	//调用模板,不用隐式转换 }
int main() {test01();test02();return 0;
}    

1.2.6 模板的局限性

局限性:模板的通用性并不是万能的

#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//模板局限性
//模板不是万能的,有些特定数据类型,需要具体化方式做特殊实现class Person{
public:Person(string n,int a){this->name = n;this->age = a;}string name;int age;
};
//对比两个数据是否相等 
template<class T>
bool myCompare(T &a,T &b){if(a==b){return true; } return false;
}
void test01(){int a=10,b=20;bool ret = myCompare(a,b);if(ret){cout<<"a==b"<<endl;}else{cout<<"a!=b"<<endl;}
}
//利用具体化Person的版本实现代码,具体化优先调用 
template<> bool myCompare(Person &a,Person &b){if(a.name==b.name && a.age == b.age){return true; } return false;
}
void test02(){Person p1("Tom",12);Person p2("Tom",12);bool ret = myCompare(p1,p2);if(ret){cout<<"p1==p2"<<endl;}else{cout<<"p1!=p2"<<endl;}
}
int main() {test01();test02();return 0;
}    

总结:
1.利用具体化的模板,可以解决自定义类型的通用化
2.学习模板并不是为了写模板,而是在STL能够运用系统提供的模板

1.3 类模板

1.3.1 类模板语法

类模板作用:建立一个通用类,类中的成员 数据类型可以不具体制定,用一个虚拟的类型来代表。

//语法
template<typename T>

解释:
1.template – 声明创建模板
2.typename – 表明其后面的符号是一种数据类型,可以用class代替

#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//类模板 
template<class NameType,class AgeType>
class Person{
public:Person(NameType n,AgeType a){this->name = n;this->age = a;}void showPer(){cout<<this->name<<"-"<<this->age<<endl;}NameType name;AgeType age;
};
void test01(){//指定数据类型 Person<string,int> p1("王",23);p1.showPer();
}int main() {test01();return 0;
}    

总结:类模板和函数模板类似,在声明模板template后面加类,此类称为类模板

1.3.2 类模板与函数模板区别

主要区别两点:
1.类模板没有自动类型推导的使用方式
2.类模板在模板参数列表中可以有默认参数

#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//类模板 与 函数模板区别 
template<class NameType,class AgeType = int>
class Person{
public:Person(NameType n,AgeType a){this->name = n;this->age = a;}void showPer(){cout<<this->name<<"-"<<this->age<<endl;}NameType name;AgeType age;
};
//1.类模板没有自动类型推导使用方式
void test01(){//指定数据类型 //Person p1("王",23);	//错误,编译器不会自动推导 Person<string,int> p1("王",23);	//正确,只能用显示指定类型 p1.showPer();
}
//2.类模板 在模板参数列表中可以有默认参数
void test02(){// template<class NameType,class AgeType> 改为 template<class NameType,class AgeType = int> //下边的int不需要写,也可以 Person<string> p1("王",23);	p1.showPer();
}  
int main() {test01();test02();return 0;
}    

总结:1.类模板使用只能用显示指定类型方式
2.类模板中的模板参数列表可以有默认参数

1.3.3 类模板中成员函数创建时机

类模板中成员函数和普通类中成员函数创建时机有区别:
1.普通类中的成员函数一开始就可以创建
2.类模板中的成员函数在调用时才创建

#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//类模板中成员函数创建时机
//类模板中成员函数在调用时才创建
class Person1{
public:void showPer1(){cout<<"showPer1 show"<<endl;}
}; 
class Person2{
public:void showPer2(){cout<<"showPer2 show"<<endl;}
}; 
template<class T>
class MyClass{
public://因为该成员函数,没有调用时候不会创建,因此可以编译通过 T obj;void func1(){obj.showPer1();}void func2(){obj.showPer2();}
};void test01(){MyClass<Person1> m1;//调用func1的时候,才会创建MyClass的成员,此时有 Person1 obj, m1.func1();	//成功 //m1.func2();	//失败 MyClass<Person2> m2;m2.func2();	//成功 
}int main() {test01();return 0;
}    

1.3.4 类模板对象做函数参数

学习目标:类模板实例化出的对象,向函数传参数的方式
一共有三种传入方式:
1.指定传入的类型 — 直接显示对象的数据类型
2.参数模板化 – 将对象中的参数变为模板进行传递
3.整个类模板化 – 将这个对象类型 模板化进行传递

#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//类模板对象做函数参数
template<class T1,class T2>
class Person{
public:Person(T1 n,T2 a){this->name = n;this->age = a;}void showPer(){cout<<this->name<<" "<<this->age<<endl;}T1 name;T2 age;
}; 
//1.指定传入类型 
void printPerson1(Person<string,int> &p){p.showPer();
}
void test01(){Person<string,int> p("孙悟空",100);printPerson1(p);
}
//2.参数模板化
template<class T1,class T2>
void printPerson2(Person<T1,T2> &p){p.showPer();cout<<"T1的数据类型"<<typeid(T1).name()<<endl; cout<<"T2的数据类型"<<typeid(T2).name()<<endl; 
}
void test02(){Person<string,int> p("猪八戒",100);printPerson2(p);
} 
//3.整个类模板化
template<class T>
void printPerson3(T &p){p.showPer();cout<<"T的数据类型"<<typeid(T).name()<<endl; 
}
void test03(){Person<string,int> p("唐僧",24);printPerson3(p);
} int main() {test01();test02();test03();return 0;
}    

总结:
1.通过类模板创建的对象,可以有三种方式向函数中进行传参
2.使用比较广泛是第一种:指定传入的类型

1.3.5 类模板与继承

当类模板碰到继承,需要注意以下几点
1.当子类继承的父类是一个类模板时,子类声明时候,要指定出父类中T的类型
2.若不指定,编译器无法给子类分配内存
3.若想灵活指定出父类中T的类型,子类也需要变为类模板。

#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//继承中的类模板
template<class T>
class Base{
public:T m;
}; 
//class Son : public Base{};	//错误,必须要知道父类中的类型,才能继承给子类 
class Son : public Base<int>{
};
void test01(){Son s;
}
//若想零或指定父类中T类型,子类也需要变类模板
template<class T1,class T2>
class Son2:public Base<T1>{
public:Son2(){cout<<"T1类型:"<<typeid(T1).name()<<endl; cout<<"T2类型:"<<typeid(T2).name()<<endl; }T1 obj;
}; 
void test02(){//父类的T是char,子类额外的属性是int Son2<int,char> s2;
}
int main() {test01();test02();return 0;
}    

总结:若父类是类模板,子类需要指定出父类中T的数据类型

1.3.6 类模板成员函数的类外实现

学习目标:掌握类模板中成员函数类外实现

#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//类模板成员函数类外实现 
template<class T1,class T2>
class Person{
public:Person(T1 n,T2 a);/*{this->name = n;this->age = a;}*/void showPer();/*{cout<<this->name<<"-"<<this->age<<endl;}*/T1 name;T2 age;
};
//构造函数类外实现
template<class T1,class T2>
Person<T1,T2>::Person(T1 n,T2 a){this->name = n;this->age = a;
} 
//成员函数类外实现
template<class T1,class T2>
void Person<T1,T2>::showPer(){cout<<this->name<<"-"<<this->age<<endl;
}
void test01(){Person<string,int> p("TOM",34);p.showPer();
} 
int main() {test01();return 0;
}    

1.3.7 类模板分文件编写

学习目标:掌握类模板成员函数分文件编写产生的问题以及解决方式
问题:类模板中成员函数创建时机是在调用阶段,导致分文件编写时,连接不到
解决:
方式1:直接包含.cpp文件
方式2:将声明和实现写到同一个文件中,并更改后缀为.hpp,hpp是约定的名称,不是强制

方式1
//person.h
#pragma once
#include<iostream>
#include <bits/stdc++.h>
using namespace std;
template<class T1,class T2>
class Person{
public:Person(T1 n,T2 a);void showPer();T1 name;T2 age;
}; 
//person.cpp
#include "person.h"template<class T1,class T2>
Person<T1,T2>::Person(T1 n,T2 a){this->name = n;this->age = a;
} 
template<class T1,class T2>
void Person<T1,T2>::showPer(){cout<<this->name<<"-"<<this->age<<endl;
}
//主函数
#include<iostream>
#include <bits/stdc++.h>
//单独包含person.h则无法运行 
//#include "person.h"
//单独包含person.h则可以运行,此时直接从cpp文件查找Person构造函数和成员函数
#include "person.cpp"
using namespace std;
void test01(){Person<string,int> p("TOM",34);p.showPer();
}
int main() {test01();return 0;
}    
将.h和.cpp内容写到一起,后缀改为.hpp
//person.hpp
#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//类模板分文件编写问题及解决
template<class T1,class T2>
class Person{
public:Person(T1 n,T2 a);void showPer();T1 name;T2 age;
}; template<class T1,class T2>
Person<T1,T2>::Person(T1 n,T2 a){this->name = n;this->age = a;
} 
template<class T1,class T2>
void Person<T1,T2>::showPer(){cout<<this->name<<"-"<<this->age<<endl;
}
//主函数
#include<iostream>
#include <bits/stdc++.h>
//包含hpp即可 
#include "person.hpp"
using namespace std;
void test01(){Person<string,int> p("TOM",34);p.showPer();
}
int main() {test01();return 0;
}    

总结:主流解决方法是第二种,将类模板成员函数写到一起,并将后缀名改为.hpp;

1.3.8 类模板与友元

学习目标:掌握类模板配合友元函数的类外和类内实现
1.全局函数类内实现:直接在类内声明友元即可
2.全局函数类外实现:需要提前让编译器知道全局函数的存在

#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//通过全局函数打印person信息 //2.全局函数 类外实现
//2.1 先声明模板类的存在 
template<class T1,class T2>
class Person;
//2.2 再声明 printPer2 的存在 
template<class T1,class T2>
void printPer2(Person<T1,T2> p){cout<<p.name<<"-"<<p.age<<endl;
} template<class T1,class T2>
class Person{//1.全局函数 类内实现//printPer相当于全局函数,然后做了Person类的友元 friend void printPer(Person<T1,T2> p){cout<<p.name<<"-"<<p.age<<endl;} //2.全局函数 类外实现 // 加空模板参数列表 // 若全局函数 是类外实现,需要让编译器提前知道这个函数的存在 friend void printPer2<>(Person<T1,T2> p);
public:Person(T1 n,T2 a){this->name = n;this->age = a;}
private:T1 name;T2 age;
};
//1.全局函数类内实现 -测试 
void test01(){Person<string,int> p("TOM",34);printPer(p);
}
//2. 全局函数类外实现 -测试 
void test02(){Person<string,int> p("Jom",24);printPer2(p);
} int main() {test01();	test02();return 0;
}    

总结:建议全局函数做类内实现,用法简单,编译器可以直接识别

1.3.9 类模板案例

实现一个普通的数组类,要求如下:
在这里插入图片描述

在这里插入图片描述

//数组.hpp
#include<iostream>
#include <bits/stdc++.h>
using namespace std;
//实现数组类
template<class T>
class Myarray{
public:Myarray(int cap){//cout<<"Myarray有参构造"<<endl; this->m_cap = cap;this->m_size = 0;this->pAddress = new T[this->m_cap];}//因为有堆区数据,因此需要深拷贝Myarray(const Myarray& arr){this->m_cap = arr.m_cap;this->m_size = arr.m_size;//cout<<"Myarray拷贝构造"<<endl; //深拷贝this->pAddress = new T[arr.m_cap];//将arr中的数据都拷贝过来for(int i=0;i<this->m_size;i++){this->pAddress[i] = arr.pAddress[i];} }//opeartor = 防止浅拷贝   a=b=cMyarray& operator=(const Myarray& arr){//cout<<"Myarray的operator调用"<<endl; //先判断原来堆区是否有数据,有则先释放if(this->pAddress != NULL){delete[] this->pAddress;this->m_cap = 0;this->m_size = 0;} //深拷贝this->m_cap = arr.m_cap;this->m_size = arr.m_size;this->pAddress = new T[arr.m_cap];//将arr中的数据都拷贝过来for(int i=0;i<this->m_size;i++){this->pAddress[i] = arr.pAddress[i];} return *this;}//尾插法void PushBack(const T& val){//判断容量是否 等于 大小if(this->m_cap == this->m_size){return;} this->pAddress[this->m_size] = val;	//数组末尾插入数据this->m_size++; 	//更新数组大小 } //尾删法void PopBack(){//用户访问不到最后一个元素,即尾删if(this->m_size==0) return;this->m_size--; }//通过下标访问数组元素 arr[0]T& operator[](int index){return this->pAddress[index];}//返回数组容量int getCap(){return this->m_cap;} //返回数组大小int getSize(){return this->m_size;} ~Myarray(){//cout<<"Myarray析构"<<endl; if(this->pAddress != NULL){delete[] pAddress;pAddress = NULL;}}
private://数组,指针指向堆区开辟的真实数组 T* pAddress;int m_cap; //数组容量int m_size;	//数组大小 }; 
//main.cpp#include<iostream>
#include <bits/stdc++.h>
using namespace std;
#include "数组类1.hpp" void test01(){Myarray<int> arr1(5);		//有参构造测试 Myarray<int> arr2(arr1);	//拷贝构造测试 Myarray<int> arr3(100);arr3 = arr1;
}
void printArr(Myarray<int>& arr1){for(int i=0;i<arr1.getSize();i++){cout<<arr1[i]<<" ";}cout<<endl;
}
void test02(){Myarray<int> arr1(5);//尾插法向数组插入数据for(int i=0;i<5;i++){arr1.PushBack(i);}	cout<<"arr1打印输出为:"<<endl; printArr(arr1);cout<<"arr1容量为:"<<arr1.getCap()<<endl; cout<<"arr1大小为:"<<arr1.getSize()<<endl; Myarray<int> arr2(arr1);cout<<"arr2尾删后打印输出为:"<<endl;arr2.PopBack();printArr(arr2);
}
//测试自定义数据类型
class Person{
public:Person(){};Person(string n,int a){this->age = a;this->name = n;}int age;string name;
}; 
void printPersonArr(Myarray<Person>& arr1){for(int i=0;i<arr1.getSize();i++){cout<<"姓名:"<<arr1[i].name<<" 年龄:"<<arr1[i].age<<endl; }
}
void test03(){Myarray<Person> arr1(10);Person p1("孙悟空",353);Person p2("韩信",153);Person p3("赵云",33);Person p4("安琪",233);//数组插入数组中arr1.PushBack(p1);arr1.PushBack(p2);arr1.PushBack(p3);arr1.PushBack(p4);printPersonArr(arr1);cout<<"personArr容量为:"<<arr1.getCap()<<endl;cout<<"personArr大小为:"<<arr1.getSize()<<endl;
}
int main() {test03();return 0;
}    

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

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

相关文章

【牛客网】:链表的回文结构(提升)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;每日一练 &#x1f337;追光的人&#xff0c;终会万丈光芒 目录 &#x1f3dd;问题描述&#xff1a; &#x1f3dd;问题分析&#xff1a; 步骤一&#xff1a;查找链表的中间节点 步骤二&am…

微信小程序 讯飞录音 点击按钮录音内容转文字

<page-meta page-style"{{ showPolish ? overflow: hidden; : }}" /> <view class"wrap"> <view class"header-tab" style"justify-content: {{typeList.length > 2 ? start : center}}"><view class&quo…

前端开发攻略---用原生JS在网页中也能实现文本转语音

1、原理 语音合成 (也被称作是文本转为语音&#xff0c;英语简写是 tts) 包括接收 app 中需要语音合成的文本&#xff0c;再在设备麦克风播放出来这两个过程。 Web API中对此有一个主要控制接口 SpeechSynthesis&#xff0c;外加一些处理如何表示要被合成的文本 (也被称为 utte…

MySql 主从同步-在原来同步基础上增加历史数据库

在MySql已经主从同步的后&#xff0c;由于有新的需求再增加1个历史数据库&#xff0c;要改原来的1个变成现在的2个数据库。在官网并没有找到类似的场景&#xff08;官方同步多个数据是从一开始就设置&#xff0c;不是后续增加的&#xff09;&#xff0c;只能结合以往的经验自己…

Weblogic一个domain建多个server(端口)

一、基本环境 名称IP端口说明AdminServer192.168.20.207001管理服务WRServer192.168.20.207001提供应用服务 1、启动weblogic服务 二、操作步骤 在weblogic控制台。环境-服务器-新建 填写服务器名称-监听地址-监听端口-点击完成 2、按照web应用 3、启动服务 /home/weblogic/…

(二十九)加油站:面向对象重难点深入讲解【重点是元类】

目录&#xff1a; 每篇前言&#xff1a;0. Python中的元类&#xff1a;1. 本文引子&#xff1a;2. Python中的mro机制&#xff1a;3. Python中类的魔法属性dict&#xff1a;注意事项&#xff1a; 拓展——内建函数dir() 4. 正式谈一谈元类&#xff08;metaclass&#xff09;:&a…

小酒馆点餐系统实现-C++项目详细过程

目录 项目介绍1、项目描述2、市场调研3、技术调研 项目设计1、概要设计2、详细设计① 数据管理模块&#xff1a;② 业务控制模块&#xff1a;③ 前端界面模块&#xff1a; 3、代码实现实现数据管理模块实现业务控制模块实现前端界面模块 项目介绍 1、项目描述 使用户可以通过…

Nacos 安全零信任实践

作者&#xff1a;柳遵飞 Nacos 作为配置中心经常存储一些敏感信息&#xff0c;但是由于误用导致安全风险&#xff0c;最常见的主要是以下两个问题&#xff1a; 1&#xff09;Nacos 暴露公网可以吗&#xff1f;不可以&#xff0c;因为 Nacos 定位是注册配置中心&#xff0c;是…

RoadBEV:鸟瞰图中的道路表面重建

1. 代码地址 GitHub - ztsrxh/RoadBEV: Codes for RoadBEV: road surface reconstruction in Birds Eye View 2. 摘要 本文介绍了RoadBEV&#xff1a;鸟瞰图中的道路表面重建。道路表面条件&#xff08;特别是几何形状&#xff09;极大地影响了自动驾驶汽车的驾驶性能。基于…

浏览器渲染机制:重排(Reflow)与重绘(Repaint)以及Vue优化策略

浏览器渲染机制是一个复杂但有序的过程&#xff0c;其目的是将HTML、CSS和JavaScript代码转化为用户可以看到和交互的视觉界面。重排&#xff08;Reflow&#xff09;与重绘&#xff08;Repaint&#xff09;是浏览器渲染过程中对页面元素进行更新的两个重要步骤&#xff0c;理解…

QML中使用正则表达式

我想在TextField控件中使用正则表达式&#xff0c;然后GPT4给出的回答是这样的&#xff1a; TextField {id: versionInputplaceholderText: qsTr("输入版本号")validator: RegExpValidator { regExp: /^[a-zA-Z0-9]*$/ } // 仅允许字母和数字width: 120 // 设置合…

Linux系统-DHCP原理与配置

目录 一.DHCP工作原理 1.了解DHCP服务 2.使用DHCP的好处 3.DHCP的分配方式 4.DHCP的租约过程 二.DHCP服务器的配置 1.首先先关闭防火墙 2. 安装DHCP有关软件包 3.查看系统的配置文件​编辑 4.设置参数 5.网络配置 一.DHCP工作原理 1.了解DHCP服务 DHCP(Dynamic Hos…