C++类和对象(基础篇)
前言:
其实任何东西,只要你想学,没人能挡得住你,而且其实学的也很快。那么本篇开始学习类和对象(C++的,由于作者有Java基础,可能有些东西过得很快)。
struct在C++中的含义:
C++兼容C中的struct的用法,并将其升级,可以在里面写函数。
// C++兼容C中的struct的用法
// C++升级struct升级成了类
// 类和对象
// 1个类 实例化 N个对象// 1.类里面可以定义函数
// 2.struct名称可以代表类型
struct Stack
{//成员函数void Init(int n = 4){_arry = (int*)malloc(sizeof(int) * n);if (nullptr == _arry){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}//成员变量int* _arry;size_t _capacity;size_t _top;
};int main()
{struct Stack s1;Stack s;s.Init();return 0;
}
我们可以不用再写 struct + 结构体名称 去创建对象,相当于已经typedef了,并且可以直接在通过对象调用函数。
这也体现了C++兼容C的特性。但是C++还是一般并不是用这种用法,一般是使用class来声明一个类。
class Stack
{void Init(int n = 4){_arry = (int*)malloc(sizeof(int) * n);if (nullptr == _arry){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}//成员变量int* _arry;size_t _capacity;size_t _top;
};int main()
{Stack s;//此时我们直接去使用里面的Init方法,发现报错s.Init();return 0;
}
访问权限:
上面我们看到报错,这是为啥?这是因为C++中有访问限定符。
1.public修饰的成员在类外可以直接访问
2.protected和private修饰的成员在类外不能直接被访问(此处protected 和 private 是类似的)
3.访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现为止
4.如果后面没有访问限定符,作用域就到 } 即类结束
5.class的默认访问权限为 private ,struct 为 public (因为 struct 要兼容C)
所以报错的原因是因为前面默认被 private 修饰了。
class Stack { public:void Init(int n = 4){_arry = (int*)malloc(sizeof(int) * n);if (nullptr == _arry){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}private://成员变量int* _arry;size_t _capacity;size_t _top; };
所以一般是成员变量私有,成员方法公有。
C++建议成员变量前面加_(这是软性建议)。
我们先创建一个Stack.h头文件,并在里面写入:
Stack.h头文件(声明函数):
#include<iostream>class Stack { public:void Init(); private:int* _a;int* _top;int* _capacity; };
此时我们在Stack.h头文件中定义一个类并声明其中的一个函数(没有定义),之后在Stack.cpp源文件中定义该函数,此时我们就需要指定类域去定义该函数。因为该函数并不是全局变量,必须指定类域。
Stack.cpp源文件中(定义函数):
void Stack::Init() {_a = nullptr;_top = 0;_capacity = 0; }
test.c源文件中(调用函数):
int main() {Stack st1;cout << sizeof(st1) << endl;cout << sizeof(Stack) << endl;return 0; }
可以发现没有计算函数的大小,因为实例化的对象调用的函数地址都是一样的,每个空间放一份,会造成空间的浪费。
所以对象占用的大小,只考虑成员变量,其大小规则和struct类似。
对于一个空类(就是里面没有任何成员变量),空类的大小为1字节,以确保每个实例都有独一无二的地址,不储存有效数据,标识对象被定义出来了。
this指针:
class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}private:int _year;int _month;int _day;
};int main()
{Date d1, d2;d1.Init(1990, 12, 1);d2.Init(1991, 12, 1);d1.Print(), d2.Print();return 0;
}
这里有一个奇怪的现象,为什么打印的不同,它怎么会知道谁传给了我?其实这里的Print方法中有一个隐含的参数-this,这个this是一个指针。
void Print(Date* this)
之后只要是成员变联名,它自动识别到了,都相当于前面加上了this指针。
void Print()
{cout << this->_year << "-" << this->_month << "-" << this->_day << endl;
}
所以其实函数相当于是这样使用的,但是默认不加。所以我们还可以这样调用:
d1.Print(&d1);
严格来说是这样写的:
void Print(Date* const this)
注意事项一:
我们先来观察以下代码:
class A
{
public:void Print(){cout << "Print()" << endl;}
private:int _a;
};int main()
{A* p = nullptr;p->Print();return 0;
}
这里是其实没有对nullptr去进行解引用,因为默认传入this指针,并不影响对Print函数的使用。
注意事项二:
再来观察一下代码:
class A
{
public:void Print(){cout << _a << endl;}
private:int _a;
};int main()
{A* p = nullptr;p->Print();return 0;
}
但这个结果是运行崩溃。我们来观察他们的区别:
this指针存在栈中,因为它是形参,也有可能是寄存器。
类的默认成员函数:
类有6个默认成员函数,编译器会自动生成6个默认成员函数(很神奇,竟然有6个)。
默认成员函数:用户没有显示实现,编译器会生成的成员函数成为默认成员函数。
构造函数:
函数名与类名相同,无返回值,对象实例化编译器自动调用对应的构造函数,构造函数可以重载。分为无参构造和有参构造,类似于初始化函数。和Java使用方式是一样的,不赘述。
当我们实例化一个对象后,会自动调用构造函数。
class Date
{
public:Date(){_year = 1;_month = 1;_day = 1;}void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << this->_year << "-" << this->_month << "-" << this->_day << endl;this->Fanacy();}void Fanacy(){cout << "hehe" << endl;}private:int _year;int _month;int _day;
};int main()
{Date d1;d1.Print();return 0;
}
观察以下代码:
Date()
{_year = 1;_month = 1;_day = 1;
}Date(int year, int month, int day)
{this->_year = year;this->_month = month;this->_day = day;
}
此时我们有两个构造函数,一个有参一个无参,并通过主函数这样调用:
int main()
{Date d1;Date d2(2, 3, 4);d1.Print();d2.Print();return 0;
}
如果是无参的不要带括号,只是为了和函数声明区分开。
Date d1;
Date d2(2, 3, 4);Date d1();//函数声明
构造函数一般喜欢写成全缺省函数。
Date(int year = 1, int month = 1, int day = 1)
{this->_year = year;this->_month = month;this->_day = day;
}
这样就可以把无参构造省略了,非常方便。
记住缺省函数定义和声明不能同时给,规定只能在声明的时候给,定义的时候不给。
如果我们写了显示的默认成员函数,那么编译器则不会在生成默认成员函数,也是和Java一样,救急不救穷。
编译器自动生成的构造函数,对于内置类型成员变量不做处理(也就是int了,double了等等基础类型),当然有些编译器会处理。
不传参数就可以调用的函数就是默认构造。
C++11为了解决初始化问题,我们可以在定义成员变量时给定缺省值。
class Date
{
public:void Print(){cout << this->_year << "-" << this->_month << "-" << this->_day << endl;}private://给缺省值int _year = 1;int _month = 1;int _day = 1;
};int main()
{Date d1;d1.Print();return 0;
}
默认构造函数只能有一个。注意:无参构造函数、全缺省函数、编译器默认生成构造函数,都可以认为是默认构造函数。
3个只能存在一个。
析构函数:
析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作使用编译器完成的。而对象在销毁是会自动调用析构函数,完成对象中资源的清理工作。
其也是一个特殊的成员函数,特征如下:
析构函数名是在类前加上字符~;无参数无返回类型;一个类只能有一个析构函数。若未显示定义,系统会自动生成默认的析构函数。注意:析构函数不能重载;对象生命周期结束时,C++编译系统自动调用析构函数。
~Date()
{cout << "这是显示调用的析构函数!" << endl;
}
析构函数我们也可以显示调用。
d1.~Date();
不是所有类都需要写析构函数,因为不需要释放空间。
编译器默认的析构函数对内置类型不做处理,对自定义类型去调用它的析构函数。
拷贝构造:
拷贝构造也是特殊的成员函数,特征如下:
拷贝构造函数是构造函数的一个重载形式;拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
若未显示定义,编译器会生成默认的拷贝构造函数。默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝或者值拷贝。
class A
{
public:A(int a = 100){_a = a;}A(A& a){_a = a._a;cout << "这里调用了拷贝构造!" << endl;}void Print(){cout << _a << endl;}
private:int _a;
};void func(A a)
{a.Print();
}int main()
{A a1(5);func(a1);return 0;
}
可以看到,我们并没有去调用任何的拷贝构造参数,但是调用了func函数之后却调用了。
这是因为这是传值传参,自定义类型对象传值传参要调用拷贝构造。 除非传入指针或者使用引用才不会调用拷贝构造。
这样就会引起死递归。所以要修改为引用:
A(const A& a)
{_a = a._a;cout << "这里调用了拷贝构造!" << endl;
}
我们一般习惯往里面写入const,是为了防止修改被拷贝的内容。
这里相当于权限的缩小。
// 下面的两种写法是等价的
A a2(a1);
A a3 = a2; //这也是拷贝构造
默认构造会实现浅拷贝,也就是不会拷贝引用类型。 默认构造会实现浅拷贝,也就是内置类型的拷贝。
总结:
如果没有管理资源,一般不要写拷贝构造,默认生成的即可使用;如果都是自定义类型成员,内置类型成员没有指向资源,也类似默认生成的拷贝构造就可以(比如用栈实现队列);一般情况下,不需要显示写析构函数,就不需要写拷贝构造;如果内部有指针或者一些值指向资源,需要显示写析构,通常就需要显示写拷贝构造完成深拷贝。
赋值运算符重载函数:
赋值运算符重载是默认成员函数,不写编译器默认生成。用户没有显示实现时,会以值的方式逐字节拷贝。和拷贝构造函数类似。
复制运算符重载不能写成全局函数,这是规定!
运算符重载:
运算符重载:是具有特殊函数名的函数,也具有其返回值类型,函数名及参数和返回值与普通函数类似。
函数名字为:关键字operator后面需要重载运算符符号。
class Date
{
public:Date(int year = 1, int month = 1, int day = 1){this->_year = year;this->_month = month;this->_day = day;}Date(Date& d){_year = d._year;_month = d._month;_day = d._day;}void Print(){cout << this->_year << "-" << this->_month << "-" << this->_day << endl;}//private://给缺省值int _year = 1;int _month = 1;int _day = 1;
};//大于
bool Compare1(const Date& d1, const Date& d2)
{if (d1._year > d2._year){//年大就大return true;} else if (d1._year == d2._year){if (d1._month > d1._month){//月大就大return true;}else if (d1._month == d2._month){//天大就大return d1._day > d2._day;}}
}//小于
bool Compare2(const Date& d1, const Date& d2)
{if (d1._year < d2._year){//年小就小return true;}else if (d1._year == d2._year){if (d1._month < d1._month){//月小就小return true;}else if (d1._month == d2._month){//天小就小return d1._day < d2._day;}}
}//等于
bool Compare1(const Date& d1, const Date& d2)
{if (d1._day == d2._day && d1._year == d2._year && d1._month == d1._month){return true;}return false;
}int main()
{Date d1(2024, 4, 10);Date d2(2024, 4, 9);cout << Compare1(d1, d2) << endl;//cout << (d1 > d2) << endl;return 0;
}
比如此时我对日期类进行比较,写了3个函数来实现,这样很麻烦,但是有操作符重载就会很方便。
cout << (d1 > d2) << endl;
比如此时我们就像通过这样来完成这个比较方法。
重载操作符必须有一个类类型参数,也就是说不能这样写:
//运算符重载是函数,以下形式非法!
int operator-(int i, int j)
.* :: sizefof ? : . 这5个运算符不能重载。
//大于
bool operator>(const Date& d1, const Date& d2)
{if (d1._year > d2._year){//年大就大return true;}else if (d1._year == d2._year){if (d1._month > d1._month){//月大就大return true;}else if (d1._month == d2._month){//天大就大return d1._day > d2._day;}}
}
之后可以直接这样使用:
cout << (d1 > d2) << endl;
插一嘴,其中.*是一个运算符(蒙了吧,我也蒙了,解释一下)。
class OB { public:void func(){cout << "func:" << endl;} };//重命名函数指针 typedef void(OB::* Ptr)();//重命名int main() {//这里必须使用&Ptr fp = &OB::func;OB tmp;//此时也就用到了.*这个操作符(tmp.*fp)();//通过函数指针调用函数return 0; }
这里我们使用到了.*。
一个类要重载哪些元素符是看需求。
class Date
{
public:Date(int year = 1, int month = 1, int day = 1){this->_year = year;this->_month = month;this->_day = day;}bool operator==(const Date& d){return _day == d._day&& _year == d._year&& _month == d._month;}private://给缺省值int _year = 1;int _month = 1;int _day = 1;
};int main()
{Date d1(20, 1, 3);Date d2(20, 1, 4);//显示调用d1.operator==(d2);//这样就没有优势了//直接写,转换调用,编译器会转换为 operator==(d1, d2)d1 == d2;return 0;
}
此时我们发现,我都是在类外定义的函数,也就意味着要把类中的成员变量都变为公有的才能这样写。
有3种解决方法:提供这些成员get和set方法;友元(后期讲);重载为成员函数。
相信各位对get和set方法都了解,我们不再赘述。
class A
{
public:A(int a = 100){_a = a;}A(const A& a){_a = a._a;cout << "这里调用了拷贝构造!" << endl;}A operator=(const A& a){//这里面最好加上返回值,这样就可以连续赋值并且不会出错_a = a._a;return *this;}void Print(){cout << _a << endl;}
private:int _a;
};int main()
{A a1(100);A a2;//拷贝一个A a3;a3 = a2 = a1;a3.Print();return 0;
}
我们在使用操作符重载的时候,最好加上返回值,这样可以连续赋值不会出错。
注意事项:
class Date
{
public:Date(int year = 1, int month = 1, int day = 1){this->_year = year;this->_month = month;this->_day = day;}Date(const Date& d){cout << "这里调用了拷贝构造" << endl;_year = d._year;_month = d._month;_day = d._day;}bool operator==(const Date& d){return _day == d._day&& _year == d._year&& _month == d._month;}//private://给缺省值int _year = 1;int _month = 1;int _day = 1;
};bool operator==(const Date& d1, const Date& d2)
{return d1._day == d2._day&& d1._year == d2._year&& d1._month == d2._month;
}Date func()
{Date d;return d;
}int main()
{Date d1(20, 1, 3);Date d2(20, 1, 4);func();return 0;
}
这里注意我们调用了func函数,返回的是Date类,会去调用类中的拷贝构造!但是可以发现,执行结果并没有执行拷贝构造中的语句,这是为啥?
但是确实会调用拷贝构造,是因为优化没有调用。
编译器在某些情况下会对代码进行优化,以提高执行效率。其中之一就是返回值优化(Return Value Optimization,RVO)。RVO 是一种优化技术,它可以避免不必要的拷贝构造函数调用。
在 func() 函数中,返回了一个局部对象 d。如果编译器启用了 RVO,它会直接将 d 放在函数调用者的位置,而不是创建临时副本。这样,拷贝构造函数就不会被调用。
但是我们严谨一点,这只是编译器帮助了我们优化,此时我们如何才能让其不拷贝?就是返回引用。
Date& func()
{Date d;return d;
}
传值返回是返回d的拷贝,引用返回是d的别名。
class Date
{
public:Date(int year = 1, int month = 1, int day = 1){this->_year = year;this->_month = month;this->_day = day;}Date(const Date& d){cout << "这里调用了拷贝构造" << endl;_year = d._year;_month = d._month;_day = d._day;}bool operator==(const Date& d){return _day == d._day&& _year == d._year&& _month == d._month;}void Print(){cout << _year << " " << _month << " " << _day << endl;}~Date(){cout << "调用了析构" << endl;_year = -1;}
//private://给缺省值int _year = 1;int _month = 1;int _day = 1;
};bool operator==(const Date& d1, const Date& d2)
{return d1._day == d2._day&& d1._year == d2._year&& d1._month == d2._month;
}Date& func()
{Date d;return d;
}int main()
{Date& d3 = func();d3.Print();return 0;
}
如果不用引用返回,返回的是d的拷贝,这里d有是临时拷贝,临时对象具有常性。 当然,d3接收以后就可以修改它的属性。
Date& func()
{Date d(1022, 1, 3);return d;
}int main()
{Date& d3 = func();d3.Print();return 0;
}
再来观察以下代码:
Date& func()
{Date d(1022, 1, 3);return d;
}int funcs()
{int a = 1;int b = 2;int c = 3;return a + b + c;
}int main()
{Date& d3 = func();d3.Print();funcs();return 0;
}
此时我们在调用一个函数,发现d3里面的值也已经改变,这是因为:
小结:
返回对象生命周期到了,会析构,传值返回。
返回对象生命周期没到,不会析构,传引用返回。
出了作用域,返回对象还没有析构,就可以用引用返回,减少拷贝。
为了优化程序,我们一般对于类的返回使用的是引用返回。
所以最好一般最好返回值,不要返回引用。
相关文章:
C++类和对象(基础篇)
前言: 其实任何东西,只要你想学,没人能挡得住你,而且其实学的也很快。那么本篇开始学习类和对象(C的,由于作者有Java基础,可能有些东西过得很快)。 struct在C中的含义: …...
Oracle导入数据中文乱码问题处理,修改客户端字符编码跟数据库的一致
前提:SQL文件打开其中中文字符是正常显示,保证导出文件中文字符正常。通过sqlplus命令导入SQL文件出现乱码,这是因为客户端跟数据库的字符集不一致导致出现乱码问题。 要SQL导入的中文正常,要确保执行导入命令的客户端字符编码跟…...
【与 Apollo 共创生态:展望自动驾驶全新未来】
1、引言 历经七年的不懈追求与创新,Apollo开放平台已陆续推出了13个版本,汇聚了来自全球170多个国家与地区的16万名开发者及220多家合作伙伴。随着Apollo开放平台的不断创新与发展,Apollo在2024年4月19日迎来了Apollo开放平台的七周年大会&a…...
【webrtc】MessageHandler 5: 基于线程的消息处理:以PeerConnection信令线程为例
peerconn的信令是通过post 消息到自己的信令线程消息来处理的PeerConnectionMessageHandler 是具体的处理器G:\CDN\rtcCli\m98\src\pc\peer_connection_message_handler.hMachinery for handling messages posted to oneself PeerConnectionMessageHandler 明确服务于 signalin…...
计算机网络 3.2网络体系结构
第二节 网络体系结构 一、网络协议 1.定义: ①通信双方共同遵守的规则。 ②为网络数据交换制定的规则、约定与标准。 ③网络实体之间通信时有关信息传输顺序、信息格式、信息内容的约定或规则。 2.协议三要素: 语法:确定协议元素的格式…...
连接HiveMQ代理器实现MQTT协议传输
先下载MQTTX: MQTTX: Your All-in-one MQTT Client Toolbox 使用线上免费的MQTTX BROKER:The Free Global Public MQTT Broker | Try Now | EMQ 打开MQTTX,创建连接,点击NEW SUBSCRIPTION,创建一个主题,这里使用test/topic,在下面Json中填写…...
springcloud报错:Failed to start bean‘webServerStartStop‘
如果你正在使用nacos进行服务注册,然后报一下错误: 那就说明的nacos没有打开,所以找到你的下载nacos的文件夹 好了,错误完美解决~...
el-checkbox 无法动态设置勾选状态
问题 cheked 值动态变化,但是勾选状态无法动态改变 解决 v-model 与:checked 同时使用 <el-checkbox class"add-shop-check" v-model"renderData[0].isCheck" :checked"renderData[0].isCheck" change"checked > selec…...
车规级低功耗汽车用晶振SG-9101CGA
车规级晶振SG-9101CGA属于爱普生9101系列,是一款可编程晶振。SG-9101CGA车规级晶振采用2.5x2.0mm封装,利用PLL技术生产,此款振荡器的频率范围从0.67M~170MHZ任一频点可选,步进1ppm,采用标准CMOS输出,最大输…...
企业是保留传统的MES还是换新的MES?
在选择上MES系统的时候,企业可以根据自身所处行业不同、当前阶段不同,以及业务需求的差异,对症下药,选择适合自己的解决方案。对于有些企业本来就有MES系统,但是已经过时过旧,就要考虑换新的MES系统了. 保留…...
2024年第六届世界软件工程研讨会(WSSE 2024)即将召开!
2024年第六届世界软件工程研讨会(WSSE 2024)将于2024年9月13-15日在日本京都举行。软件工程领域的发展离不开各位专家学者和业界精英的共同努力和贡献。WSSE 2024将就软件工程领域的最新研究成果、实践经验和发展趋势进行深入交流和探讨,汇聚…...
Linux网络编程:TCP编程实现
目录 1、前言 2、函数介绍 2.1 socket函数 与 通信域 2.2 bind函数 与 通信结构体 2.2.1 domain通信地址族 与 通信结构体 2.2.2 IPv4地址族结构体 2.2.3 通用地址族结构体 2.2.4 示例:为套接字fd绑定通信结构体addr 2.3 listen函数 与 accept函数 …...
小剧场短剧影视小程序源码_后端PHP
项目运行截图 源码贡献 https://githubs.xyz/boot?app42 部署说明 linux/win任选 PHP版本:7.3/7.2(测试时我用的7.2要安装sg扩展 ) 批量替换域名http://video.owoii.com更换为你的 批量替换域名http://120.79.77.163:1更换为你的 这两个…...
C语言总结三:数组(压缩版)
一,数组概念 定义:相同类型元素的集合 二,一维数组 1,语法:type arr_name[常量值]; 2,初始化:int arr[5]{1,2,3,4,5}; 3,类型:int [5] 4,使用࿱…...
我独自升级崛起怎么玩 我独自升级崛起游玩教程分享
《我独自升级:ARISE》是一款预计在 Android、iOS 和 PC 平台推出的动作 RPG,故事内容基于网络漫画版本改编,讲述世界各地出现「次元传送门」,而少部分人类觉醒了可以对抗传送门中怪物的「猎人」能力,玩家可以在故事模式…...
前端上传大文件
在前端实现大文件上传,通常涉及以下几个关键步骤和技术要点,以确保上传过程既高效又稳定: 1. 文件切片 目的:将大文件分割成多个小块,以减少单次请求的负担,提高上传速度,并且增强上传的稳定性…...
Kompas AI图片转换器:高效解决格式不兼容问题
最新Kompas AI:一键转换图片格式,提升工作效率 在数字化的世界里,图片已成为我们交流和分享信息不可或缺的媒介。然而,不同的场景往往需要不同格式的图片,这时,一个高效的图片格式转换工具就显得尤为关键。…...
自动驾驶规划与控制技术解析
目录 1. 自动驾驶技术 2.定位location 3. 地图HD Map 4 预测prediction 5 自动驾驶路径规划 6. 自动驾驶路径规划 7. 规划planning 8. 视频路径 1. 自动驾驶技术 2.定位location 3. 地图HD Map 4 预测prediction 5 自动驾驶路径规划 6. 自动驾驶路径规划 7. 规划…...
计算机等级考试常见问题
目录 计算机二级报什么好? 计算机等级考试可以直接考4级吗 计算机等级考试包括什么...
C语言实战项目--贪吃蛇
贪吃蛇是久负盛名的游戏之一,它也和俄罗斯⽅块,扫雷等游戏位列经典游戏的行列。在编程语言的教学中,我们以贪吃蛇为例,从设计到代码实现来提升大家的编程能⼒和逻辑能⼒。 在本篇讲解中,我们会看到很多陌生的知识&…...
【LAMMPS学习】八、基础知识(5.3)Body particles体粒子
8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语,以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…...
【3D目标检测】常见相关指标说明
一、mAP指标 mean Average Precision(平均精度均值),它是目标检测和信息检索等任务中的重要性能指标。mAP 通过综合考虑精度和召回率来衡量模型的总体性能。 1.1 精度(Precision) 表示检索到的目标中实际为正确目标…...
QT设计模式:工厂模式
基本概念 工厂模式是一种创建型设计模式,用于将对象的创建逻辑与使用者分离,以实现对象的创建和使用的解耦。工厂模式提供了一个统一的接口来创建对象,而客户端代码只需通过该接口来请求所需的对象,而不需要知道具体的对象创建细…...
【电路笔记】-容抗
容抗 文章目录 容抗1、概述2、容抗示例13、容抗示例 24、容抗示例 35、分压器修订6、总结1、概述 容抗是电容器的复阻抗,其值随应用频率而变化。 与不依赖于频率的电阻不同,在交流电路中,电抗受电源频率的影响,并且其行为方式与电阻类似,两者都以欧姆为单位测量。 电抗会…...
基于若依框架搭建网站的开发日志(一):若依框架搭建、启动、部署
RuoYi(基于SpringBoot开发的轻量级Java快速开发框架) 链接:开源地址 若依是一款开源的基于VueSpringCloud的微服务后台管理系统(也有SpringBoot版本),集成了用户管理、权限管理、定时任务、前端表单生成等…...
Android中Fragment失去焦点的场景
在Android开发中,Fragment的生命周期方法onPause()会在以下几种情况下被调用: 当Fragment所在的Activity开始与其他Activity进行交互时,例如按下Home键或其他Activity获得焦点,导致当前Activity失去焦点,从而使得所有关…...
Linux变量的认识及环境变量配置详解
文章目录 1、变量的划分2、局部变量3、全局变量4、环境变量4.1、概述4.2、配置临时环境变量4.3、配置永久环境变量4.3.1、用户级配置文件1)配置方法一:~/.bashrc文件2)配置方法二:~/.profile文件3)配置方法三ÿ…...
【excel】数据非数值导致排序失效
场景 存在待排序列的数值列,但排序失效,提示类型有问题: 解决 选中该列,数据→分列 而后发现提示消失,识别为数字,可正常排序。...
软件网关--Nginx
Nginx 的多功能用途 Nginx 是构建现代化分布式应用程序的重要工具,它的功能远不止于高性能的 Web 服务器和反向代理。它还能充当 API 网关,处理前后端通信、认证、授权、监控等任务。以下是 Nginx 的主要用途: 前后端通信代理:N…...
sourceTree push失败
新电脑选择commit and push,报错了,不过commit成功,只不过push失败了。 原因是这个,PuTTYs cache and carry on connecting. 这里的ssh选择的是 PuTTY/Plink,本地没有这个ssh密钥,改换成openSSHÿ…...
无锡网站建设专家/网络营销课程总结
1. 淘宝商品信息定向爬虫 链接: https://www.taobao.com/ 2. 实例编写 2.1 整体框架 # -*- coding: utf-8 -*-import requests import redef getHTMLText(url):print("")# 对获得的每个页面进行解析 def parsePage(ilt, html):print("")#将商品…...
个人备案网站会影响吗/推广小程序
认识<hr>标签,添加水平横线 语法: html4.01版本 <hr> xhtml1.0版本 <hr /> 注意: 1. <hr />标签和<br />标签一样也是一个空标签,所以只有一个开始标签,没有结束标签。 2. <hr…...
wordpress数据可视化/如何免费推广自己的网站
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼}i;}average average/N; /* 计算总平均分*//*输出*/printf("NO.\tname\tscore1\tscore2\tscore3\ttotal\tave\n");for(bstu;b{printf("%d\t%s\t",b->num,b->name);for(j0;j<3;j)printf("%d\t&q…...
湖南英文网站建设/seo推广排名重要吗
undefined:声明了变量,但是没有赋值undeclared:没有声明变量就直接使用 如上图,num 就是undefined,arr 则是 undeclared。...
傻瓜式网站建设/网络舆情分析报告范文
文章目录1 概述2 第三方库2.1 搜索2.2 安装3 扩展3.1 Flask 安装1 概述 1. 场景:无法使用 pip install Flask 命令直接安装,如(1) 公司内网限制(2) 电脑没有网络2. 目录切换命令(若需要) C: cd C:\Users\..\Python37\Lib 2 第…...
店铺推广引流/长沙seo推广
主要有6步: 第 1 步 计算出各活动所需的成本(包括应急储备); 第 2 步 汇总得出工作包的成本(包括应急储备); 第 3 步 汇总各个工作包,得到控制账户的成本(包括应急储备&a…...