【C++初阶】第四站:类和对象(下)(理解+详解)
前言:
本篇知识点:初始化列表、explicit关键字、static成员、友元、内部类、匿名对象、编译器的优化
专栏:C++初阶
目录
再谈构造函数
1️⃣构造函数体赋值
2️⃣初始化列表
explicit关键字
static成员
1.static概念
2.static特性
面试题
友元
友元函数
友元类
内部类
内部类概念
优化面试题
匿名对象
匿名对象和有名对象
拷贝对象时的一些编译器优化
知识点回顾:
示例(包含讲解):
传值传参和传值返回
构造+拷贝构造
连续的拷贝构造
拷贝构造+赋值重载(无法优化)
再次理解类和对象
再谈构造函数
对于MyQueue 不需要写它的构造函数,编译器自动生成,会调用它的默认构造。
但是如果Stack类不提供默认构造给你,那就得实现显示调用,该怎么办呢?
有两种办法。
1️⃣构造函数体赋值
class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};
class Date
{
public:Date(int year=2024, int month=1, int day=1)//构造函数初始化,只能初始化一次//赋值{_year = year;//可以多次赋值_year = 2023; _year = 2021; //..._month = month;_day = day;}
private:int _year;int _month;int _day;
};
2️⃣初始化列表
#include<iostream>
using namespace std;
class Date
{
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}void Print(){cout << _year << "/" << _month << "/" << _day;}
private:int _year;int _month;int _day;
};
int main()
{ Date d1(2024, 1, 1);d1.Print();return 0;
}
执行如下:
💦引用成员变量💦const成员变量💦自定义类型成员(且该类没有默认构造函数时)

class Date
{
public://初始化列表是每个成员定义的地方//不管你写不写,每个成员都要走初始化列表Date(int year, int month, int day, int& i):_year(year), _month(month), _a(i), _refi(i),_x(100)//显示给值了{//赋值//_day = day;}void func(){++_refi;++_refi;}//private下面如果成员变量右边给了值,都叫做缺省值
private:int _year;//每个成员声明int _month;int _day;//C++11支持给缺省值,这个缺省值给初始化列表//如果初始化列表没有显示给值,就用这个缺省值//必须定义时初始化,也就是说以下这三个成员变量必须出现在初始化列表const int _x=1;//如果显示给值了,就不用这个缺省值int& _refi;A _a;
};
//能用初始化列表就用初始化列表初始化
//有些场景还是需要初始化列表和函数体混着用
int main()
{int n = 0;Date d1(2023, 7, 28, n);d1.func();cout << n << endl;return 0;
}
执行:对_refi就是对着n操作
#include<iostream>
using namespace std;
class Time
{
public:Time(int hour = 0):_hour(hour){cout << "Time()" << endl;}
private: int _hour;
};
class Date
{
public:Date(int day){}
private:int _day;Time _t;
};
int main()
{Date d(1);
}
执行:



explicit关键字
class A
{
public://explicit A(int i)A(int i):_a(i){cout << "A(int i):"<<i<< endl;}A(const A& aa):_a(aa._a){cout << "A(const & aa)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};
struct SeqList
{
public:void PushBack(const A& x){//...扩容_a[_size++] = x;}size_t size() const{return _size;}//读const A& operator[](size_t i)const{assert(i < _size);return _a[i];}//读/写A& operator[](size_t i){assert(i < _size);return _a[i];}
private://C++11A* _a = (A*)malloc(sizeof(A) * 10);size_t _size = 0;size_t _capacity = 0;
};
int main()
{A aa1(1);A aa2 = 2;return 0;
}
经过编译器优化之后,以下的两个代码是等价的:
A aa1(2);//直接构造 <==> A aa1 = 2
解析:
在早期的编译器中,当遇到下面的一行代码时,会处理成:用2调用A构造函数生成一个临时对象(tmp),再用这个对象(tmp)去拷贝构造aa1
A aa1 = 2;//先构造,再拷贝构造
上面的代码等价于下面这两步:
A tmp(2);
A aa2(tmp);
但是,C++支持单参数构造函数的隐式类型转换:
编译器会再优化,优化用2直接构造,所以当我们遇到像A aa1 = 2的式子时,实际上编译器已经转换成了A aa1(2),这就叫隐式类型转换
同时在c++中,不想让隐式类型发生,就在构造函数前面加个explicit

在C语言中我们也讲了隐式类型转换:无论是值拷贝还是说加了引用的,都会生成临时变量的。
static成员
1.static概念
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化
2.static特性
- 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
代码如下:#include<iostream> using namespace std; class A { public:A() {++n;++m;}A(const A& t){++n;++m;}~A(){--m;} private:int a;//4 bytestatic int n;static int m; }; int main() {cout << sizeof(A) << endl;return 0; }
2.静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
解析思路:当我们要计算A这个类,累计创建了多少个对象(用n表示),正在使用的多少个对象(用m表示)以之前的知识,我们首先会在全局定义两个变量![]()
经过以下代码验证之后,我们发现,如果定义全局的变量,会被外面随意修改
![]()
此时的话,我们试下把n和m定义在class A的private内,但是这样每一个对象在定义的时候,都会创建一个n和m,此时n和m是每一个对象的成员了,不是用来统计有几个对象,明显不能这样定义。
这时候如果被static修饰,这两个成员变量就位于静态区了,叫做静态成员变量,需要注意的地方有:
代码如下:
class A { public: private:int a;//4 bytestatic int n;//静态成员的声明static int m;//静态成员的声明 }; //在类外面定义 int A::n = 0; int A::m = 0;
还有要注意的;
3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员来访问
静态成员变量被public修饰时:
代码如下:
include<iostream> using namespace std; class A { public:A(){++n;++m;}A(const A& t){++n;++m;}~A(){--m;} //private:static int n;static int m; }; // 静态成员变量的定义初始化 int A::n = 0; int A::m = 0;int main() {A aa1;cout << A::n << " " << A::m << endl;//1.通过类名突破类域进行访问cout << aa1.n << " " << aa1.m << endl; //2.通过类对象突破类域进行访问A* ptr = NULL;cout << ptr->n << " " << ptr->m;//3.通过空指针解引用成员突破类域 }
当静态成员变量被private修饰时:
我们当然可以定义被public修饰的成员函数,然后此时被static修饰的两个静态成员n和m通过创建对象aa1,接着aa1.Print()就可以打印出对象的个数,
但如果我定义一个匿名对象,接着调用Print函数,这时候会多出一个n(累计创建的对象),干扰打印的逻辑了。
我们可以借鉴上面静态成员变量突破类域的方式,引出我们静态成员函数的三种突破类域的方式
代码如下:
#include<iostream> using namespace std; class A { public:A(){cout << "A()" << endl;++n;++m;}A(const A& t){++n;++m;}~A(){--m;}//静态成员函数的特点:没有this指针static int GetM(){return m;}static void Print(){//x++;//不能访问非静态,因为没有thiscout << m << " " << n << endl;} private://这样定义不行,这样的话每一个对象都有一个n和m,//int m;//int n;// 不符合题意,因为这是来统计对象个数的//静态成员变量属于所有A对象,属于整个类//声明//累积创建了多少个对象static int n;//正在使用的还有多少个对象static int m; };int A::n = 0; int A::m = 0;int main() {A aa;//三种突破类域的方式A::Print();//通过类名调用静态成员函数进行访问aa.Print();//通过实例化的对象调用成员函数进行访问A* ptr = NULL;ptr->Print();//通过空指针调用静态成员函数进行访问return 0; }
![]()
代码如下:
//4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员 #include<iostream> using namespace std; class A { public:static void Print(){cout << x++ << endl;} private:int x;//非静态成员变量static int a;//静态成员变量 }; int main() {A x;x.Print(); }
答:不能 , 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
答:可以。 因为静态成员函数和非静态成员函数都在类中,在类中不受访问限定符的限制。
#include<iostream>
using namespace std;
class A
{
public:void Notstatic(){Print();//<-------非静态调用调用静态 }//两种写法static void Print(){cout << a << endl;}/*static int Print(){cout << a << endl;return a;}*/
private:int x;//非静态成员变量static int a;//静态成员变量
};
int A::a = 10;
int main()
{A x;x.Notstatic();
}
执行:
面试题
#include<iostream>
using namespace std;
class Sum//定义一个名为Sum的类
{
public:Sum()//构造函数,当创建Sum对象时自动调用{_ret +=_i;// 每次构造函数被调用时,将静态成员变量_i的当前值累加到静态成员变量_ret上_i++; //紧接着递增静态成员变量_i的值}static int GetRet()//定义一个静态成员函数GetRet,用于获取静态成员变量_ret的值{return _ret;//直接返回静态变量_ret的值}
private:
//定义两个静态私有成员变量
// 静态成员变量属于类,不是某个对象所有,而是所有对象共享,并且在整个程序生命周期内只初始化一次static int _i;//初始化为1,每次构造函数调用时递增static int _ret;// 初始化为0,用于累计构造函数调用次数
};//对静态成员变量进行初始化(定义)
int Sum::_i = 1;
int Sum::_ret = 0;
//定义另一个名为Solution的类
class Solution {
public:// 定义成员函数Sum_Solution,接收一个整数参数nint Sum_Solution(int n) {Sum a[n];return Sum::GetRet();}
};
友元
友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。友元分为:友元函数和友元类
友元函数
- 友元函数可访问类的私有和保护成员,但不是类的成员函数
- 友元函数不能用const修饰
- 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
- 一个函数可以是多个类的友元函数
- 友元函数的调用与普通函数的调用原理相同
我们之前在:【C++初阶】第一站:C++入门基础(上) -- 良心详解-CSDN博客
简单了解过关于cout(流插入),cin(流提取)的知识
现在我们来回顾一下:
在之前的印象中,当我们遇到关于内置类型(int,float,double等),可以直接使用cout和cin进行输出和输入:
原因是什么呢,通过查阅资料可以发现:i 和 j 通过操作符重载间接实现了类似成员函数的功能。
cin是istream类型的对象,cout是ostream类型的对象
在C++中,内置类型是直接支持cout流插入<<和cin流提取>>,这并不是什么自动识别类型,是运算符重载和函数重载罢了,库里面支持把内置类型作为成员函数,重载了
这时候,我们创建Date类的一个自定义类型的对象,使用cout和cin输出和输入会发现编译错误:
我们可以看到,隐含的this指针,占据着这个流插入成员函数的第一个参数的位置,与main函数内调用的位置不相符,cout是ostream类型的对象,但是到了成员函数,第一个位置是Date*类型
既然它的位置不相符,那么我们可以这样写吗:
可以是可以,但是流插入的本质是:应该是对象流入到console里面去,而不是console流入到对象里 ,对于流提取同理
这时候我们把位于Date.h里原本成员函数的声明注释掉:
我们在全局定义一个<<重载的函数,定义成全局的声明,此时经过编译后,又引发了一个新问题:
面对这样的情况,该如何去纠正:
在类的外部要想访问内部私有成员,用友元声明:在类的公有和私有声明都可以
我们发现就可以编译通过了:
并且类型的顺序也是匹配的:
但是当咱们连续输出两个自定义对象的时候,编译就不会通过了,看下面解析:
这时候我们把.h里面的友元的返回值改成ostream&、全局声明和.cpp里面的返回值也改成一样:
对于流提取,并不能给声明加const:
总结:
内置类型,可以使用<<>>是因为函数重载加运算符重载
自定义类型使用的方式是重载这个流插入和流提取的运算符
class Date
{
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}
// d1 << cout; -> d1.operator<<(&d1, cout); 不符合常规调用
// 因为成员函数第一个参数一定是隐藏的this,所以d1必须放在<<的左侧ostream& operator<<(ostream& _cout){_cout << _year << "-" << _month << "-" << _day << endl;return _cout;}
private:int _year;int _month;int _day;
};

友元类
- 友元关系是单向的,不具有交换性。
- 友元关系不能传递
- 友元关系不能继承,在继承位置再给大家详细介绍
class Time
{friend class Date; // 声明日期类为时间类的友元类,//则在日期类中就直接访问Time类中的私有成员变量
public:Time(int hour = 0, int minute = 0, int second = 0): _hour(hour), _minute(minute), _second(second){}private:int _hour;int _minute;int _second;
};
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}void SetTimeOfDate(int hour, int minute, int second){// 直接访问时间类私有的成员变量_t._hour = hour;_t._minute = minute;_t._second = second;}private:int _year;int _month;int _day;Time _t;
};
内部类
内部类概念


总结:1.B类 受A类域和访问限定符的限制,其实它们是两个独立的类
2.内部类默认就是外部类的友元 -- 内部类可以访问外部类,外部类不能访问类部类

class A
{
private:static int k;int h;
public:class B // B天生就是A的友元{public:void foo(const A& a){cout << k << endl;//OKcout << a.h << endl;//OK}};
};
int A::k = 1;
int main()
{A::B b;b.foo(A());return 0;
}
执行:
优化面试题
求1+2+3+...+n_牛客题霸_牛客网 (nowcoder.com)
class Solution {class Sum {public:Sum(){_ret += _i;_i++;}};public:int Sum_Solution(int n) {Sum a[n];return _ret;}private:static int _i;static int _ret;
};
int Solution::_i = 1;
int Solution::_ret = 0;
匿名对象
#include<iostream>
using namespace std;
class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};
class Solution {
public:int Sum_Solution(int n) {//...return n;}
};
int main()
{A aa1;// 不能这么定义对象,因为编译器无法识别下面是一个函数声明,还是对象定义//A aa1();// 但是我们可以这么定义匿名对象,匿名对象的特点不用取名字,// 但是他的生命周期只有这一行,我们可以看到下一行他就会自动调用析构函数A();A aa2(2);// 匿名对象在这样场景下就很好用,当然还有一些其他使用场景,这个我们以后遇到了再说Solution().Sum_Solution(10);return 0;
}
执行:
匿名对象和有名对象
例子
拷贝对象时的一些编译器优化
知识点回顾:
C++默认兼容C语言,默认生成的拷贝构造函数对内置类型会完成值拷贝(跟结构体拷贝一样)但是又规定自定义类型传值传参过程中,符合拷贝构造:拿一个以及存在的对象去初始化另一个对象
为什么要规定调拷贝构造?因为直接搞值拷贝,会有很大的问题,比如说像栈、顺序表、链表这样的类(析构两次),对象里面可能还有一个指针指向一块空间,这时候就要完成深拷贝,那想让这个拷贝正确该怎么办呢,就要自己去写那个深拷贝
所以c++在这一块完成了完美的兼容,对于日期类就算要浅拷贝(不写,编译器默认生成的拷贝构造),编译器有着个性化处理,对于栈要自己写深拷贝,对于日期类写不写都行
示例(包含讲解):
比如下面这个例子中:传值传参引发了对象的拷贝,拷贝要调用拷贝构造,拷贝出aa1的副本aa,然后出了作用域aa先析构,回到main函数之后,出了作用域aa1再调析构
可以想象一下,假设我仅仅只想调用一下Print()有没有必要使用拷贝构造?没有吧。
我们要给这个形参加上引用,同时加上const,这样的话就不会引发拷贝,也保护了对象不可修改:
同时插播一下,这两者是有着显著区别的:


传值传参和传值返回

class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}A(const A& aa):_a(aa._a){cout << "A(const A& aa)" << endl;}A& operator=(const A& aa){cout << "A& operator=(const A& aa)" << endl;if (this != &aa){_a = aa._a;}return *this;}~A(){cout << "~A()" << endl;}
private:int _a;
};
void f1(A aa)
{}
A f2()
{A aa;return aa;
}
int main()
{// 传值传参A aa1;f1(aa1);cout << endl;// 传值返回f2();cout << endl;return 0;
}
对于析构的分析
对于f2(),仅此于f2(),我们分析一下析构:
第一次析构:在
f2
函数内部,局部变量aa
在return aa;
语句处会触发一次析构。这是因为aa
是f2
函数的局部对象,当函数执行完毕时,局部对象的生命周期结束,因此会调用析构函数。第二次析构:
f2
函数返回的是A
类的一个对象,但由于它是通过值返回的,所以在f2()
调用处会创建一个临时对象接收返回值。然而,由于这个临时对象在表达式结束之后没有被存储到任何地方,因此它也会在表达式(也就是f2() )结束时立即被销毁,从而触发第二次析构。
构造+拷贝构造
一个表达式,连续的步骤里面,连续的构造会被合并
f1(1):隐式类型,连续构造(构造函数)+拷贝构造->优化为直接构造
f1(A(2)):一个表达式中, 连续构造(构造函数)+拷贝构造->优化为一个构造
连续的拷贝构造
拷贝构造+赋值重载(无法优化)
//上文有A类的定义
A f2()
{A aa;return aa;
}
int main()
{// 一个表达式中,连续拷贝构造+赋值重载->无法优化A aa1;aa1 = f2();cout << endl;return 0;
}
执行:
拷贝构造的aa,返回的临时拷贝,也就是回到main函数之后的那个临时对象(黄色字),要等到赋值运算符重载完毕之后,才调的析构
再次理解类和对象
类和对象篇就此结束,接下来是内存管理。
🔧本文修改次数:0
🧭更新时间:2024年3月1日
相关文章:

【C++初阶】第四站:类和对象(下)(理解+详解)
前言: 本篇知识点:初始化列表、explicit关键字、static成员、友元、内部类、匿名对象、编译器的优化 专栏:C初阶 目录 再谈构造函数 1️⃣构造函数体赋值 2️⃣初始化列表 explicit关键字 static成员 1.static概念 2.static特性 面试…...

redis的基本数据类型(一)
redis的基本数据类型 1、redis1.1、数据库分类1.2、NoSQL分类1.3、redis简介1.4、redis应用1.5、如何学习redis 2、redis的安装2.1、Windows安装2.2.1、客户端redis管理工具 2.2、Linux安装🔥2.2.1、redis核心文件2.2.2、启动方式2.2.3、redis桌面客户端1、redis命令…...

Windows无法识别exFAT格式怎么办?
Windows通常无法读取Mac格式的驱动器。如果使用Apple的HFS Plus将驱动器格式化为exFAT,默认情况下Windows无法读取exFAT驱动器,即使exFAT文件系统与Mac和Windows兼容。事实上,一些制造商销售的“Mac驱动器”是用这种限于Mac的文件系统预先格式…...
AI大模型的发展趋势?
大模型的发展趋势主要体现在以下几个方面: 1、模型规模的增长: 随着数据量和计算能力的不断增加,大型模型的规模也在不断扩大。模型参数数量、层数等指标不断刷新,以应对更复杂的任务和更大规模的数据。 2、多模态融合ÿ…...
List去除重复数据的五种方式
1、使用 LinkedHashSet 删除 arraylist 中的重复数据 LinkedHashSet 是在一个 ArrayList 删除重复数据的最佳方法。LinkedHashSet 在内部完成两件事: 删除重复数据 保持添加到其中的数据的顺序 Java 示例使用 LinkedHashSet 删除 arraylist 中的重复项。在给定的示例…...

VUE3自定义文章排行榜的简单界面
文章目录 一、代码展示二、代码解读三、结果展示 一、代码展示 <template><div class"article-ranking"><div class"header"><h2 class"title">{{ title }}</h2></div><div class"ranking-list&qu…...

七通道NPN 达林顿管GC2003,专为符合标准 TTL 而制造,最高工作电压 50V,耐压 80V
GC2003 内部集成了 7 个 NPN 达林顿晶体管,连接的阵列,非常适合逻辑接口电平数字电路(例 如 TTL,CMOS 或PMOS 上/NMOS)和较高的电流/电压,如电灯电磁阀,继电器,打印机或其他类似的负…...
若依springboot接入feign踩坑记录
问题情境: 简单的项目采用了若依的前后端分离版本单体应用,之前采用forest请求调用第三方接口,改为feign接口调用后,引入feign报错 error creating bean with name ‘configurationPropertiesbean’ 解决方案: spri…...
Lumerical Script ------ Error: <文件目录> line x:syntax error
Lumerical Script ------ Error: <文件目录> line x:syntax error 引言正文引言 在 Lumerical Script ------ Error: line 0: syntax error 一文中我们介绍了一种常见的错误提示信息。这里,我们使用类似的代码,介绍另一种提示错误提示信息。 正文 有时候,当我们在…...

Opencv基础与学习路线
Opencv Opencv每一篇目具体: Opencv(1)读取与图像操作 Opencv(2)绘图与图像操作 Opencv(3)详解霍夫变换 Opencv(4)详解轮廓 Opencv(5)平滑处理 具体Opencv相关demo代码欢迎访问我的github仓库(包含python和c代码) demo代码 文章目录 Opencv一…...

Python装饰器的使用详解
目录 1、函数装饰器 1.1、闭包函数 1.2、装饰器语法 1.3、装饰带参数的函数 1.4、被装饰函数的身份问题 1.4.1、解决被装饰函数的身份问题 1.5、装饰器本身携带/传参数 1.6、嵌套多个装饰器 2、类装饰器 装饰器顾名思义作为一个装饰的作用,本身不改变被装…...

基于springboot+vue的党员教育和管理系统
博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 主要内容:毕业设计(Javaweb项目|小程序|Pyt…...
三个伪类让你的CSS代码更加优雅
公众号:程序员白特,欢迎一起交流学习~ 原文:CSS整洁之道——:is()、:where()和:has()的用法 - 掘金 (juejin.cn) 让我们写出优雅界面的CSS,它也总是把自己进化得更加优雅。 今天我们花5分钟时间学习三个优雅的CSS伪类:…...

幻兽帕鲁联机服务器搭建
幻兽帕鲁联机服务器搭建 开通云服务器 云主机购买|香港云服务器|香港云主机|美国云服务器|弹性云主机租用尽在-特网科技 建议选择4核心 16G内存 10M带宽,可满足6-15人游玩 下载安装脚本 windows系统: 下载 http://downinfo.myhostadmin.net/palserver/install…...

京东商品优惠券API获取商品到手价
item_get_app-获得JD商品详情原数据 公共参数 请求地址: jd/item_get_app 名称类型必须描述keyString是调用key(必须以GET方式拼接在URL中)secretString是调用密钥api_nameString是API接口名称(包括在请求地址中)[item_search,i…...

Flutter Version Manager (FVM): Flutter的版本管理终极指南
Flutter笔记 Flutter Version Manager (FVM) - 文章信息 - Author: 李俊才 (jcLee95) Visit me at: https://jclee95.blog.csdn.netEmail: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/article/details/136300307 my-websit…...

Docker技术概论(3):Docker 中的基本概念
Docker技术概论(3) Docker 中的基本概念 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://…...

死记硬背spring bean 的生命周期
1.bean的生命周期 我们平常经常使用类似于new Object()的方式去创建对象,在这个对象没有任何引用的时候,会被gc给回收掉。而对于spring而言,它本身存在一个Ioc容器,就是用来管理对象的,而对象的生命周期也完全由这个容…...

海外网红营销策略:如何将红人粉丝有效转化为品牌忠实粉丝?
在数字化时代,社交媒体已经成为品牌推广和营销的不可或缺的一部分。随着海外网红营销的崛起,品牌们纷纷将目光投向这个新兴的营销领域。然而,仅仅依赖网红的影响力来达到品牌传播的效果是不够的,更为重要的是如何将网红的粉丝转化…...

java之Bean对象
1. 什么是Bean? Bean被实例化的,是被Spring框架所管理的Java对象。 Spring容器会自动完成Bean的实例化。将所创建的的Bean自动注入到Ioc容器中以供调用。 spring框架中 IOC容器中管理的对象就是Bean对象 2. 第三方bean Bean 因为第三方bean࿰…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...

Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...