类和对象(三)

news2025/1/18 19:03:56

目录

前言

1.再谈构造函数

1.1 初始化列表

1.2 explicit关键字

 2.static成员

2.1 概念

 2.2 特性

3.友元

3.1. 友元函数

3.2 友元类

4.内部类

5.匿名对象

 6.拷贝对象时的一些编译器优化


前言

今天小编给大家介绍的就是类最后的相关内容,希望大家好好学习理解,以加深大家对类的理解。


1.再谈构造函数

之前给大家介绍了构造函数的相关内容,对于变量的初始化我们都是放在函数体内进行直接赋值的,但是函数体内赋值并不是成员变量定义的地方,我们可以将其理解成为成员变量赋值的位置,比如:

class Date
{
public:
Date(int year, int month, int day)
 {
     _year = year;
     _month = month;
     _day = day;
 }
private:
int _year;
int _month;
int _day;
};

我们这里构造函数进行的就是对成员变量进行赋值的操作,那我们进行定义的地方是在哪里呢?这就需要我们引入一个新的概念,也就是初始化列表。

1.1 初始化列表

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟
一个放在括号中的初始值或表达式。
这里我给大家简单的演示一下:
class Date
{
public:
Date(int year, int month, int day)
  : _year(year)
  , _month(month)
  , _day(day)
 {}
private:
int _year;
int _month;
int _day;
};

但是这里仍然有几点我们需要注意一下:

1. 每个成员变量在初始化列表中最多只能出现一次(初始化只能初始化一次)
2. 类中包含以下成员,必须放在初始化列表位置进行初始化:
引用成员变量
const成员变量
对于引用和const修饰的成员必须在定义的时候初始化,所以我们对于该变量是必须放在初始化列表初始化的。
自定义类型成员(且该类没有默认构造函数时)

但对于没有默认构造的自定义类型,我们一定是需要写出(需要在括号后加上非默认构造的参数),因为系统并不知道该如何调用,如果该自定义类型具有自己的默认构造,我们仍然要将其写入初始化列表,我们就需要更据该参数情况进行传参。

这里还有一点就是:我们不写初始化列表,每个成员变量也会自己走初始化列表。

3. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,
一定会先使用初始化列表初始化。
在讲解第四点需要注意的要点之前,这里我需要给大家介绍一道题目:
class A
{
public:
    A(int a)
       :_a1(a)
       ,_a2(_a1)
   {}
    
    void Print() {
        cout<<_a1<<" "<<_a2<<endl;
   }
private:
    int _a2;
    int _a1;
};
int main() {
    A aa(1);
    aa.Print();
}
A. 输出1  1
B.程序崩溃
C.编译不通过
D.输出1  随机值

对于上面这道题目,可能大家都会选择 A答案,这里我们运行一下看看结果如何:

 我们可以看到输出的是我们的D答案,那为什么该是选择D答案的呢?这就和我们的第四点有关了。

4. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关(这里小编建议,以后大家应该尽可能得将声明和初始化的顺序安排成一致)

1.2 explicit关键字

介绍这个关键字之前,小编先给大家介绍一段程序:

class Date
{
public:
	Date(int year)
		:_year(year)
	{
		cout << "Date(int year, int month, int day)" << endl;
	}
	Date(Date& d1)
	{
		cout << "Date(Date& d1)" << endl;
		_year = d1._year;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1=1;
}

这里我们看到主函数,这里我们看到了这里有个语句是Date d1=1,那么这个语句会发生什么过程呢?之前的话如果=后接的是一个对象,那么我们这里就会调用拷贝构造去初始化这个对象,但是我们这里后面接的是一个常数,那么实际上这里会发生一个隐式转换的过程,这里发生隐式转换有个前提的要求是构造函数中对应的形参要和等号接的值保持一致,那么隐式转换这个过程会发生什么呢?

这里首先会调用构造函数,将1这个值构造成一个对象,再调用拷贝构造函数,去对这个对象进行初始化,那么这里是否会发生小编上面所说的这个过程呢,这里我们看一下运行结果

 这里我们发现我们只是调用了构造函数,那为什么没有拷贝构造函数呢?这就和编译器的优化有关,具体的小编在文章末会给大家具体介绍。

那么这里和我们的这个关键字又有什么关系呢?

从上面我们可以知道:

构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值
的构造函数,还具有类型转换的作用

而用我们的explicit关键字去修饰构造函数,就会避免改发生类型转换。这里我给大家演示一下:

 2.static成员

2.1 概念

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。

这里小编就给大家介绍一道面试题,以便大家更好的理解这个static修饰符,这里的题目要求是:实现一个类,计算程序中创建出了多少个类对象

题目分析:这里我们可以根据每当我们要创建一个对象,要么利用构造函数,要么就是利用拷贝构造函数,而我们销毁一个对象势必就会调用其析构函数,因此我们可以利用一个变量来记录这个变化,但是这个变量不能是局部的,否则当出了局部作用域就会被销毁而无法完全记录这个过程,因此这里势必我们需要利用一个静态变量去记录这个过程,对于静态变量,我们有全局和static这两种,但是对于全局变量我们在程序内的任何地方都可以使用,这就导致了该变量会在其他位置被改变,导致结果不准确的风险,依次这里我们这里使用static修饰类内变量,且该变量是被private修饰的,这就导致我们只可以通过调用类内相关函数才可以去改变其值。那么下面我们直接看代码。

#include<iostream>
using namespace std;
class A
{
public:
	A() { ++_scount; }
	A(const A& t) { ++_scount; }
	~A() { --_scount; }
	static int GetACount() { return _scount; }
private:
	int _a = 1;//(成员变量————属于每个一个类对象,存储在对象里面)
		static int _scount; //(静态成员变量————属于类,属于类每个对象共享,存储在静态区)
};
int A::_scount = 0;
void TestA()
{
	cout << A::GetACount() << endl;
	A a1, a2;
	A a3(a1);
	cout << A::GetACount() << endl;
}
int main()
{
	TestA();
}

这里我们运行一下,查看该值是否正确:

 2.2 特性

1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区

2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明

3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问

4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员(指定类域和访问限定符就可以访问)

5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制

这里根据上面我们还需要补充一点的是:非静态可以调用静态函数,但是静态函数不能调用非静态函数,因为非静态函数需要this指针,但是静态函数没有this指针。(仅限于类内)。

这里小编再给大家讲解一道题目,以加深大家对static这个修饰符的理解:

题目要求:设计一个类,在类外面只能在栈上创建对象, 设计一个类,在类外面只能在堆上创建对象

题目分析:首先我们需要想到,我们的构造函数是支持在栈上也支持在堆上创建的,而且我们每次构造一个对象势必会使用到构造函数,因此这里首先我们不能让类外对象直接访问到类内构造函数,而我们创建在不同存储空间对象就需要我们在类内进行处理,而如何让我们的类外去调用到我们处理过的函数呢?通过对象调用显得不太可能,那么这里我们只能通过类::函数名,对该函数进行访问,因此这里我们就需要使用到static修饰我们特殊处理的函数,代码如下:

class A
{
public:
//栈上创建
static A GetStackObj()
{
A aa;
return aa;
}
//堆上创建
static A* GetHeapObj()
{
return new A;
}
private:
A()
{}
private:
int _a1 = 1;
int _a2 = 2;
};
int main()
{
A::GetStackObj();
A::GetHeapObj();
return 0;
}

3.友元

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

友元分为:友元函数和友元类

3.1. 友元函数

在介绍友元函数之前,小编这里要给大家介绍两个操作符重载函数,首先是 . <<流插入运算符,>>流提取运算符,之前为了访问到类内成员变量,我们基本上是将操作符的重载写在类内的,这里我们以日期类为例,看看我们的这两个操作符写在类内重载会发生什么情况:

这里需要和大家提前说明的是我们的cout是存在于ostream类中的,而我们的cin是存在于istream类中的,因为我们的流插入和流提取都是支持连续的,根据操作符的性质该都是从左往右执行的,所以我们执行完后需要返回。

#include<iostream>
using namespace std;
class Date
{
public:
	Date(int year, int month, int day)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
	ostream& operator<<(ostream& out)
	{
		out << _year << "-" << _month << "-" << _day << endl;
		return out;
	}
	istream& operator >>  (istream& in)
	{
		in >> _year >> _month >> _day;
		return in;
	}
	
private:

	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2002, 2, 2);
	d1 << cout;
	d1 >> cin;
	d1 << cout;
	return 0;
}

这里我们运行一下:

以上我们可以看到的是我们重载该运算符后,该调用方式和我们的习惯是不一致的,原因是由于这里的对象会被默认成为第一个参数,如果我们按我们平时的习惯去调用,就会出现:

这里我们的解决方式就是将其写全局,但是我们该如何访问到类内私有成员呢?

1.写一个公共函数去获得

这里虽然可以实现,但是过于繁琐,我们不推荐,大家可以自己尝试一下。

2.友元函数

友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字,这里我们直接看我们的改造过程

#include<iostream>
using namespace std;
class Date
{
	//函数友元
	friend ostream& operator<<(ostream& out, const Date& d);
	friend istream& operator >>  (istream& in, Date& d);
public:
	Date(int year, int month, int day)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
	
	
private:

	int _year;
	int _month;
	int _day;
};
ostream& operator<<(ostream& out,const Date&d)
{
	out << d._year << "-" << d._month << "-" << d._day << endl;
	return out;
}
istream& operator >>  (istream& in,Date&d)
{
	in >> d._year >>d._month >> d._day;
	return in;
}
int main()
{
	Date d1(2002, 2, 2);
	cout << d1;
	cin >> d1;
	cout<< d1;
	return 0;
}

这里我们调用一下,看看其过程:

这里我们还需要给大家说明几个要点:

友元函数可访问类的私有和保护成员,但不是类的成员函数

友元函数不能用const修饰

友元函数可以在类定义的任何地方声明,不受类访问限定符限制

一个函数可以是多个类的友元函数

友元函数的调用与普通函数的调用原理相同

 

3.2 友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
友元关系是单向的,不具有交换性。
比如 Time 类和 Date 类,在 Time 类中声明 Date 类为其友元类,那么可以在 Date 类中直接
访问 Time 类的私有成员变量,但想在 Time 类中访问 Date 类中私有的成员变量则不行。
友元关系不能传递
如果 C B 的友元, B A 的友元,则不能说明 C A 的友元。
友元关系不能继承,在继承位置再给大家详细介绍。

这里就给大家简单的实现一下类的友元

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;
};

4.内部类

概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限

注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。(内部类在没有创建对象的时候是不占空间的,因为内部类在某个类中只是一个声明)

特性:

1. 内部类可以定义在外部类的public、protected、private都是可以的。

2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。

3. sizeof(外部类)=外部类,和内部类没有任何关系。

4.内部类也受访问限定符限制

#include<iostream>
using namespace std;
class A
{
private:
	static int k;
	int h;
public:
	class B // B天生就是A的友元(内部类可以访问外部类的成员)
	{
	public:
		void foo(const A& a)
		{
			cout << k << endl;//OK
			cout << a.h << endl;//OK
		}
	};
};
int A::k = 1;
int main()
{
	A::B b;
	b.foo(A());

	return 0;
}

5.匿名对象

对于匿名对象的介绍,小编这里就直接在代码中给大家说明一下:

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;
}

这里大家配合上面的讲解,小编这里在给大家说明归纳这几个要点:

1.首先匿名对象的构造方式是:类名(对应构造函数的参数)

2.匿名对象的生命周期只有一行,这里我们运行一下,这个程序让大家观察一下此过程

 我们可以看到第二次构造函数执行后,后续马上就执行了析构函数,这就说明了该匿名对象的生命周期就只有一行。

3.匿名对象具有常性

这里小编给大家演示一下,这里的类和上面一致,小编只是改了一下主函数的部分内容

int main()
{
	A& b = A();
	return 0;
}

这里我们会发现编译器会给我们报一个这样的错误:

 但是当我们把程序改为:

int main()
{
	const A& b = A();
	return 0;
}

可以发现我们的程序是没有任何错误的:

 4.对于const A& ra=A()此时的const引用会延长匿名对象的生命周期,生命周期就会延长至当前函数的作用域

这里我们写几个变量给大家观察一下:

int main()
{
	A a(1);
	const A& b = A();
	A d(5);
	return 0;
}

调用可以发现:

这里我们第二次调用构造函数并没有马上销毁该匿名对象。

 6.拷贝对象时的一些编译器优化

在传参和传返回值的过程中,一般编译器会做一些优化,减少对象的拷贝,这个在一些场景下还是非常有用的。这里我们直接看代码,看其的具体现象:

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;
// 隐式类型,连续构造+拷贝构造->优化为直接构造
f1(1);
// 一个表达式中,连续构造+拷贝构造->优化为一个构造
f1(A(2));
cout << endl;
// 一个表达式中,连续拷贝构造+拷贝构造->优化一个拷贝构造
A aa2 = f2();
cout << endl;
// 一个表达式中,连续拷贝构造+赋值重载->无法优化
aa1 = f2();
cout << endl;
return 0;
}

这里我们运行一下,看该是否进行了优化

这里很明显就是我们在连续的构造和拷贝构造构造会省略拷贝构造,这也就告诉我们在传参和返回值时最后将会出现构造和拷贝构造的情况写在同一行。

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

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

相关文章

僵尸进程?孤儿进程?为什么他有如此惨烈的身世...

文章目录 &#x1f490;专栏导读&#x1f490;文章导读&#x1f337;认识进程状态&#x1f33a;如何查看进程状态 &#x1f337;R状态&#x1f33a;引例&#x1f33a;如何观察 &#x1f337;S状态与D状态&#x1f33a;S状态&#x1f341;如何观察 &#x1f33a;D状态 &#x1f…

【机器学习】Yellowbrick 包的理解和说明

文章目录 一、介绍二、Visualizers2.1 Classification Visualization2.2 Clustering Visualization2.3 Feature Visualization2.4 Model Selection Visualization2.5 Regression Visualization2.6 Target Visualization2.7 Text Visualization 一、介绍 首先是包的安装过程&am…

Reid strong baseline 代码详解

本项目是对Reid strong baseline代码的详解。项目暂未加入目标检测部分&#xff0c;后期会不定时更新&#xff0c;请持续关注。 本相比Reid所用数据集为Markt1501&#xff0c;支持Resnet系列作为训练的baseline网络。训练采用表征学习度量学习的方式。 目录 训练参数 训练代…

前端开发之this.$options.data的使用

前端开发之this.$options.data的使用 前言效果图vue2中使用vue3中使用 前言 this.$options.data:初始化对象 效果图 vue2中使用 this.$options这是一个Vue的特性&#xff0c;它可以让你访问组件的选项对象。你可以使用this.$options.data.call(this)来获取组件的初始数据&am…

pytorch模型转ONNX

目录 1. ONNX 2. pytorch 转 ONNX 3. 加载 ONNX 文件 4. Netron 1. ONNX 一般来说&#xff0c;pytorch训练好的模型是不能够直接用于生产环境&#xff0c;有很多的地方没有优化 而ONNX 格式可以兼顾不同框架的模型&#xff0c;相当于一个中间人的角色。这样部署到不同的环…

msvcr120.dll丢失怎样修复,学这三招就可以修复好

年前才买的新电脑&#xff0c;今天在打开软件ps软件的时候&#xff0c;电脑就提升msvcr120.dll文件丢失&#xff0c;无法执行此代码。刚刚开始以为是电脑的系统没有装好&#xff0c;经过我一下午时间的研究&#xff0c;原来是电脑msvcr120.dll文件丢失一般都是下载到垃圾软件&a…

软件测试后浪太强了,前浪有点顶不住啊,真难受...

想和大家说的话 8年前军哥刚进入到IT行业&#xff0c;现在发现学习软件测试的人越来越多&#xff0c;今天想根据军哥的行业经验再结合自己的一些看法给大家提一些建议。 最近聊到软件测试的行业内卷&#xff0c;越来越多的转行和大学生进入测试行业&#xff0c;导致软件测试已…

证件照片如何换背景底色,3个免费制作证件照的方法,简单易学

在日常生活中&#xff0c;我们经常需要用到证件照&#xff0c;比如&#xff1a;找工作需要简历上附带有证件照&#xff0c;还有办理学生证、身份证也需要提交证件照。 不同的平台有时候提交的要求&#xff08;背景底色、大小等&#xff09;也不一样&#xff0c;如果你不想每次…

缺少dll文件怎么办?修复dll文件的多种方法

缺少dll文件怎么办&#xff1f;当您试图启动某个应用程序或游戏时&#xff0c;可能会遇到“缺少DLL文件”的错误提示。DLL文件是动态链接库文件的缩写&#xff0c;它们包含在计算机上的许多应用程序和游戏中&#xff0c;并且是确保这些应用程序和游戏正常运行的重要部分。当出现…

秒懂!项目安全问题-SM4加解密

项目安全问题一直被人们研究&#xff0c;当前端路径上通过?status这种拼接参数时&#xff0c;参数的值在浏览器路径栏上非常醒目&#xff0c;是很容易被人恶意修改的&#xff0c;比如该用户并没有编辑权限&#xff0c;但有心之人却可以通过修改参数status的值把see改成edit&am…

【DataX】将hive表数据导入ES

目录 一、环境 二、创建hive测试表 三、Es写入插件包 四、配置json 五、数据同步 1、执行命令 2、查看es结果 一、环境 DataX&#xff1a;windows安装 Es版本&#xff1a;7.9.0 二、创建hive测试表 CREATE TABLE teacher(name string,age int )row format del…

抖音未来的发展趋势|成都欢蓬信息

抖音未来的发展趋势&#xff0c;近年来随着互联网技术的发展&#xff0c;小视频app也逐渐走入大家的日常生活中&#xff0c;闲着的时候打开手机抖音APP&#xff0c;就可以刷到世界各地人们分享的视频和直播&#xff0c;下面一起看看抖音未来的发展趋势 一、抖音的现状   据权…

【 五子棋对战平台(java_gobang) 】

文章目录 一、核心功能及技术二、效果演示三、创建项目扩展&#xff1a;WebSocket 框架知识 四、需求分析和概要设计五、数据库设计与配置 Mybatis六、实现用户模块功能6.1 数据库代码编写6.2 前后端交互接口6.3 服务器开发6.4 客户端开发 七、实现匹配模块功能7.1 前后端交互接…

构建新一代智慧园区移动应用以推动数字转型

随着智慧城市的建设和智慧园区的崛起&#xff0c;智慧园区数字一体化建设成为园区发展的重心&#xff0c;当然数字转型离不开移动应用的整合服务。 在过去的几年中&#xff0c;智慧园区移动应用已经发展成为园区管理和服务的重要手段之一&#xff0c;为企业和员工提供了更加便…

知行之桥EDI系统2023版功能介绍——概览页面

登录知行之桥EDI系统2023版&#xff0c;即可看到概览页面。默认情况下&#xff0c;会显示过去7天的各项指标。用户可以在页面右上角&#xff1a;显示过去的数据 下拉列表中手动选择需要的时间段&#xff0c;如&#xff1a;24小时、3天、7天等。 关键指标的自定义配置 概览页面…

如何将exe注册为windows服务,直接从后台运行

如何将exe注册为windows服务&#xff0c;直接从后台运行 使用instsrvsrvanywindow64位系统安装配置 window32位系统安装 使用instsrvsrvany 这是地址&#xff1a;链接: 网盘地址 提取码: h2za 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 window64位系统 安…

[OOD设计] - 电梯系统设计

明确主要需求 首先需要设计电梯系统的基本工作流程&#xff0c;一个简单电梯系统主要就是两个主要功能&#xff1a; 乘客在电梯外按下按钮时&#xff0c;电梯系统会驱动一个电梯来接人乘客在电梯内部按下楼层按钮时&#xff0c;电梯系统会驱动该电梯到达指定楼层 根据需求来…

泰克Tektronix AFG31021 任意波函数发生器产品资料

AFG31021是一款高质量、多功能的任意波形发生器&#xff0c;可以生成高精度、高分辨率的波形信号。该产品的主要特点包括&#xff1a; 可以生成任意波形信号&#xff0c;内置多种标准波形&#xff0c;如正弦波、方波、三角波、锯齿波等&#xff0c;也可以通过用户自定义来生成…

支付从业者转型路在何方?

近来&#xff0c;整个支付行业&#xff0c;已经“卷”出了新高度。 营销上电销卷地推&#xff0c;工单卷电销&#xff0c;POS机具则是退押金卷不退押金&#xff0c;无押金卷退押金”&#xff0c;互相“卷”得不亦乐乎。 与此同时&#xff0c;支付圈子里聊的永远是“成本上升”…

微信小程序是怎么做的?

微信小程序是一种轻量级的应用&#xff0c;它可以在微信内部直接使用&#xff0c;无需下载和安装。那么&#xff0c;微信小程序是怎么做的呢&#xff1f; 微信小程序制作的大概步骤 微信小程序制作主要包括以下几个步骤&#xff1a; ①注册小程序账号 ②在小程序制作工具创…