[C++]:1.初识C++和C语言缺陷补充。

news2024/11/27 5:25:12

初识C++和C语言缺陷补充

  • 一.主要内容:
  • 二.具体内容:
    • 一: 作用域
      • 1.命名空间:
      • 2.函数声明和定义:
      • 3.不存在命名冲突的情况:
    • 二.输入输出:
      • 1.基本输入输出:
      • 2.关于std的展开:
    • 三.函数:
      • 1.缺省参数(部分):
      • 2.全缺省:
      • 3.缺省参数的定义和参数的传递
      • 4.函数重载:
        • >1.参数个数:
        • >2.类型:
        • >3.类型顺序:
        • >4.总结:如果存在一种情况:
      • 5.为什么出现函数重载?(编译链接的原理):
        • 1.预编译(预处理)
        • 2.编译
        • 3.汇编
        • 4.链接:
      • 6.引用:
      • 1.基本概念:
        • 1-1:关于函数的引用:
        • 1-2:引用用的特殊:
        • 1-3:常引用:
      • 2.常规用法:
        • 1.作为函数参数:
        • 2.作为函数返回值:
      • 3.特殊用法:
        • 1.解决方法一:二级指针:
        • 2.解决方法二:引用:
      • 4.总结:
      • 7.内联函数:
        • 1.概念:
        • 2.inline的优缺点:

一.主要内容:

1.对于C++ 来说是在C语言的基础之上刚开始进行对C语言的缺陷进行了优化解决,加入面向对象的编程思想,加入了非常多有用的库,和一些编程范式。对于C语言比较属性那么对于C++的学习是有帮助的。
2.那么C++对于C语言的一些些缺陷是在那一些方面呢?包括有作用域,IO方面,函数方面,指针,宏方面进行了修改。

二.具体内容:

一: 作用域

1.命名空间:

1.在C语言中存在这样的一个情况我们使用一个全局变量的时候有可能在命名变量名称的时候和C语言标准库中的内容产生冲突(1.我们的标准库在全局展开会和自己的变量名称冲突 2.在我们做一个项目的时候我们定义的变量名函数名和其他人会有冲突)。

请添加图片描述
请添加图片描述
请添加图片描述

2.解决方法:使用命名空间这一个C++提供的语法:namespace关键字,它可以把我们本地定义的内容进行包裹,在正常开始访问变量的时候默认只访问全局。下面这个代码没有进入命名空间在全局只有一个rand函数所以打印出来了一个随机值。

请添加图片描述

3.如何使用自己的命名空间呢?
:: 域作用限定符 命名空间名称+域作用限定符去访问这个命名空间。
命名空间中可以放什么东西呢?
变量名,函数声明,函数定义,结构体,联合体,枚举,等等。

请添加图片描述

4.如果出现了在一个命名空间中有两个这个同名称的变量或者函数等等。非常容易解决这个问题因为我们C++是支持命名空间的嵌套的:

请添加图片描述

2.函数声明和定义:

1自己的函数声明放在自己的命名空间中自己的定义放在自己的命名空间中在我们进行定义和声明分离的时候我们要把定义和声明放在同一个空间中:

#include"Stack.h"

namespace sfpy_stack {
	//函数定义:
	//1.初始化:
	void InitStack(struct Stack* st1)
	{
		assert(st1 != NULL);

		StData* tmp = (StData*)malloc(sizeof(StData) * 4);
		if (tmp == NULL)
		{
			perror("malloc file");
			exit(-1);
		}
		st1->st = tmp;
		st1->top = 0;
		st1->capacity = 4;
	}

	//2.插入数据:
	void StackPush(struct Stack* st1, StData x)
	{
		if (st1->top == st1->capacity)
		{
			StData* tmp = (StData*)realloc(st1->st,(sizeof(StData)*((st1->capacity)*2)));

			if (tmp == NULL)
			{
				perror("malloc file");
				exit(-1);
			}

			st1->st = tmp;
			st1->capacity = (st1->capacity) * 2;
		}

		st1->st[st1->top] = x;
		st1->top++;
	}

	//3.数据遍历:
	void StackPrint(struct Stack* st1)
	{
		assert(st1 != NULL);
		for (int i = 0; i < st1->top; i++)
		{
			printf("%d ", st1->st[i]);
		}
	}

	//4.栈销毁
	void StackDestory(struct Stack* st1)
	{
		free(st1->st);
		st1->st = NULL;
	}
}

??????????????????????????????????????????

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>


namespace sfpy_stack {

	typedef int StData;

	typedef struct Stack{
		StData* st;
		int top;
		int capacity;
	}sk;

	//函数声明:

	//1.初始化:
	void InitStack(struct Stack* st1);

	//2.插入数据:
	void StackPush(struct Stack* st1, StData x);

	//3.数据遍历:
	void StackPrint(struct Stack* st1);

	//4.栈销毁
	void StackDestory(struct Stack* st1);
}


#include"Stack.h"

int main()
{
	//1.定义一个结构体:
	struct sfpy_stack::Stack st;
	//1-1:在有struct的情况下
	//我们定义结构体变量使用上面这个方法
	//sfpy_stack::struct Stack st2;

	//1-2:重命名之后就可以使用下面这个方法:
	//sfpy_stack::sk st2;
	
	//2.进行初始化:
	sfpy_stack::InitStack(&st);

	//3.数据插入:
	sfpy_stack::StackPush(&st, 1);
	sfpy_stack::StackPush(&st, 2);
	sfpy_stack::StackPush(&st, 3);
	sfpy_stack::StackPush(&st, 4);
	sfpy_stack::StackPush(&st, 5);
	sfpy_stack::StackPush(&st, 6);

	//4.栈数据的打印:
	sfpy_stack::StackPrint(&st);

	//4.进行销毁:
	sfpy_stack::StackDestory(&st);

	return 0;
}

3.不存在命名冲突的情况:

1.如何打开命名空间:使用using namespace spfy_stack;
2.打开命名空间就可以不使用域限定操作符直接使用变量函数等。
3.在我们的个人作业不存在命名冲突的情况使用using namespace spfy_stack ,可以在你去使用命名空间内容就可以不使用域限定操作符:
请添加图片描述

二.输入输出:

1.基本输入输出:

1.C++ 官方标准库iostream。
2.我们的std空间名称是C++的官方定义的输入输出相关的命名空间。

  1. 使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含< iostream >头文件以及按命名空间使用方法使用std
  2. cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含< iostream >头文件中。
  3. <<是流插入运算符,>>是流提取运算符。
    请添加图片描述
  4. 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。C++的输入输出可以自动识别变量类型
    请添加图片描述
  5. 实际上cout和cin分别是ostream和istream类型的对象,>>和<<也涉及运算符重载等知识。请添加图片描述

2.关于std的展开:

1.std是C++ 标准库中的一个命名空间他的展开是需要考虑情况的因为对于一个由多个人完成的项目来说这个空间是不可以展开的。
2。在自己的练习上面去使用using namespace std;打开标准库的这一个命名空间,这样可以不需要去使用标准库名称和域限定操作符。
3-1:换行的多种方法:
3-1:1.在字符串中结尾使用\n. 2.在输出到控制台的单词后面加一个“\n”.3.使用endl结尾这个是std这个命名空间中的一个用来换行的根第2个是同样的效果。
endl==end line

请添加图片描述

4:如果存在一种情况需要换行多次但是其他的std中的有冲突(不允许完全打开命名空间)我们可以只打开命名空间中的一个操作符。

三.函数:

1.缺省参数(部分):

如果我们给这个函数的这个变量进行了传参我们就使用我们的传参,如果我们没有去进行传参就使用默认的缺省参数
2.作用:我们开辟栈空间知道要看多少空间和不知道需要开多少空间:
2-1:不知道要开多少空间我们就使用默认开辟空间的值后面动态增长:
2-2:知道要开多少空间我们就使用传参的值一下开辟好空间不需要多次判断扩容:
2-3:函数相同在存在一个缺省值的情况下完成了多个功能。

注意:如果生命与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。

请添加图片描述
请添加图片描述

2.全缺省:

1.函数的参数全部都具有缺省值这样我们对于一个函数就有n+1种调用方式:为什么可以使用相同的函数名称呢?我们接下来再说!
请添加图片描述

3.缺省参数的定义和参数的传递

1`.缺省参数值只能从右往左给。
2.函数传实参只能从左往右。
3.如果我们给了全部缺省我们不能跳跃的进行实参传递。
4.函数的声明和定义中不要同时出现缺省参数我们一般在函数的声明中给缺省值,如果函数的定义和声明中都有缺省值我们的编译器不知道使用哪一个缺省值。

请添加图片描述

4.函数重载:

1.函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表==(参数个数 或 类型 或 类型顺序)==不同,常用来处理实现功能类似数据类型不同的问题。

>1.参数个数:

请添加图片描述

>2.类型:

请添加图片描述
请添加图片描述

>3.类型顺序:

请添加图片描述请添加图片描述
请添加图片描述

>4.总结:如果存在一种情况:

事情A单独出现必须去做。
事情B单独出现必须去做。
事情A和B同时出现怎么办?编译器面对这样的情况不知道怎么办的那就报错:
A:妈妈掉水里了 B:爸爸掉水里了

5.为什么出现函数重载?(编译链接的原理):

为什么C++支持函数重载但是C语言不支持函数重载呢?

定义:Func.cpp
声明:Func.h
主函数:text2.cpp

//Func.cpp
int  add(double b, int c)
{
	return b + c;
}

int add(int b, double c)
{
	return b + c;
}
//Func.h
#include<iostream>

int  add(double b, int c);

int add(int b, double c);


//text2
#include"Func.h"

using namespace std;


int main()
{
	//1.参数不同:
	cout << add(2.2, 3) << endl;

	cout << add(2, 3.3) << endl;

	return 0;
}

这里我们通过linux进行预编译,编译,汇编,链接整个过程:

1.预编译(预处理)

1.头文件的展开,宏替换,条件编译,去掉注释
生成:通过预编译生成==func.i test2.i文件

请添加图片描述

2.编译

2.编译进行:语法分析,词法分析,语意分析,符号汇总。
生成:通过编译生成汇编代码:Func.s text2.s请添加图片描述
通过vim观察一下汇编代码我们看一看两个函数的地址名称:
关于linux下的函数定义的汇编代码通过什么方法命名的呢?
_Z + (函数名字符个数) +(函数名称)+参数类型的首字母:
通过观察下面两个函数名称我们就可以看出来!!!
请添加图片描述

通过vs上的反汇编我们可以观察到两个函数定义call的地址是不相同的!
在vs下定义相同函数名称的函数重载的方法比较linux下的是,windows下是通过特殊符号(对应一个类型)进行的函数名称的汇编定义!!
请添加图片描述

3.汇编

在linux下汇编后生成的二进制文件是是以.o结尾的文件,在linux下生成的是以.obj
为后缀的二进制文件。
请添加图片描述

4.链接:

链接机器会把各种.o文件和并对文件需要的库进行链接生成可执行的二进制文件 .out
如果我们的函数没有定义在func.cpp中那么到链接的时候会显示链接错误说明链接错误是发生在链接的过程中!!!!。这个时候我们的代码已经生成了二进制的机器码了。但是在链接的过程中找不到函数的定义了!!!

请添加图片描述

6.引用:

1.基本概念:

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间

请添加图片描述
请添加图片描述

1-1:关于函数的引用:

请添加图片描述

1-2:引用用的特殊:

1.引用必须要初始化:
2.一个变量可以被多次引用:
3.一个引用只能被初始化一次之后如果a=b(a已经引用初始化过了b对a是赋值操作)

请添加图片描述

1-3:常引用:

1.常引用:常表示的是常变量。
2.给一个常量取别名:
2-1:访问打印 或者 进行改变(常量是不可以改变的)

图1
请添加图片描述

从图1到图2是一种权限的缩小,原来的引用可以干两个事情
1.通过引用改变–引用的变量的值。2。获取引用变量的值进行打印:
3.图二中的引用只能做(获取引用变量的值进行打印)

图2:
请添加图片描述

图三:
请添加图片描述

图四:
请添加图片描述

图五:
在这里插入图片描述

图6
在这里插入图片描述

图7:
请添加图片描述
图8:

请添加图片描述
请添加图片描述

总结我们观察上面的两个图片我们会发现引用和指针在汇编实现的时候是相同的但是题目有不同的作用:
1.在语法上r是ch的别名改变r就是改变ch
2.但是在底层r是开辟了一个4字节空间用来保存地址:

2.常规用法:

1.作为函数参数:

swap函数用来交换数值:
请添加图片描述

2.作为函数返回值:

在这里插入图片描述

如何保存函数返回值:
1.函数返回值比较小的时候就用一个寄存器去保存函数返回值:
2.函数返回值比较大的时候在main和函数栈帧空间中开辟一个位置保存这个返回值。
3ret的值取绝于函数栈帧销毁之后是否清理空,清理的化就是随机值不清理就是上面的情况但是范围一个不属于当前代码的空间是比较危险。

请添加图片描述

怎么样引用才可以作为函数返回值呢:
1.这个变量在函数栈帧销毁的时候它不会被销毁:
1-1:static静态变量(存放在静态区)
1-2:开辟在堆区的变量(存放在堆区)

请添加图片描述

请添加图片描述

3.特殊用法:

1.我们在模拟实现单链表的时候因为进行开始的头节点的改变和头插都需要改变头节点而传了一个二级指针的操作:

请添加图片描述

1.解决方法一:二级指针:

我们通过二级指针的方法就可以直接改变我们头节点的地址:
请添加图片描述

2.解决方法二:引用:

通过上面的知识我们知道int是可以有别名的int*有别人名的。当然结构体类型有别名的。结构体指针类型有别名。

请添加图片描述

4.总结:

1.引用在语法上就是另一个变量的别名,指针是存储了另一个变量的地址。
2.引用必须初始化,指针无所谓初始化。
3.引用初始化是一种传址,后面的赋值都是一种改变变量数值的操作。
4.引用初始化一个变量之后就不可以在引用其他变量,然鹅指针可以在任何时候指向另一个同类型的实体:
5.sizeof 中的含义不同因为我引用是你的别名应该有你的所有属性所以sizeof大小应该满足引用类型的字节大小,指针类型是地址地址在32为平台下就是4字节:
6.引用++ 就是引用的实际个体数值++,指针++就是向后移动应该类型的字节大小。
7.有多级指针但是没有多级引用。
8.访问实体的方式不同,指针靠解引用,引用靠编译器自己处理。
9.引用比指针使用起来更加安全,这个安全是相对的内容。

7.内联函数:

关于宏:
优点:
1.不需要开辟函数栈帧,节省空间。
2.宏的效率会快一些。
缺点:
1.容易出现优先级的问题。
2.不可以调试
3.宏的内容过多会产生空间的浪费。
4.宏是没有类型检查的。

1.概念:

一个inline加在一个函数的前面就让这个函数获得了宏的所有优点但是并没有宏的一些缺陷(优先级,函数调试,类型检查),内联提高了函数的运行效率:

请添加图片描述

1.因为inline是一个对代码的优化,默认不会打开这个代码优化。
请添加图片描述
请添加图片描述

打开之后的结果:
请添加图片描述

2.inline的优缺点:

1.inline是具有不错的优点但是inline不是一个非常好的处理方法。
2.inline本质上是一个用空间换时间的做法,如果编译器把函数当作内联函数处理。那么在代码进行预编译的时候我们就进行替换,好处:节省了调用函数栈帧的时间消耗,缺点:导致目标文件变大。
3.inline对于编译器只是一个建议,不同的的编译器对于inline的实现的机制可能不同,一般函数比较小,不是递归并且频繁调用的函数可以去用inline修饰。
4.inline不建议定义和声明分开会导致连接错误因为inline函数需要展开但是如果定义和声明分离展开是没有内容的(找不到函数地址链接找不到的)。

5.优点:
1.有宏的所有优点,没有宏的缺点
2.频繁调用一个小函数效率是比较高的:
6.缺点:
1.内联函数比较大,就会大大使用了目标空间。
2.使用一个较大函数我们内联就都会去编译函数代码,对于正常的函数调用只会编译一条函数代码。

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

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

相关文章

Docker逃逸---SYS_PTRACE浅析

一、产生原因 用户授予了容器SYS_PTRACE权限&#xff0c;并且与宿主机共享一个进程命名空间(--pidhost)&#xff0c;使得容器内可以查看到宿主机的进程&#xff0c;攻击者可以利用进程注入&#xff0c;反弹shell&#xff0c;从而实现逃逸 二、利用条件 1、容器有SYS_PTRACE权…

解决安装nvm以后windows cmd无法找到npm/yarn命令的问题

安装了nodejs多版本管理工具nvm以后&#xff0c;会出现windows cmd无法找到npm/yarn命令的问题 只要一运行npm/yarn就会提示&#xff1a;不是内部命令&#xff0c;找不到运行路径之类的。 解决办法&#xff1a;首先打开windows环境变量的配置&#xff0c;查看NVM_SYMLINK指向…

55 零钱兑换

零钱兑换 题解1 DP另一种解法(更好记) 题解2 递归 给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。 计算并返回可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额&#xff0c;返回…

点赞“美丽南苑人”㉒ | 施晨阳:以青春之名 赴亚运之约

为积极培育和践行社会主义核心价值观&#xff0c;引导和激励辖区群众学习身边先进典型的道德品质和价值追求&#xff0c;进一步发挥“美丽人物”的典型示范和带动引领作用&#xff0c;南苑街道开启“点赞‘美丽南苑人’”专栏&#xff0c;向大家讲述“美丽南苑人”的故事&#…

选择共享wifi项目哪个公司好?!

当今社会&#xff0c;无线网络成为了人们生活中必不可少的一部分。在日常生活中&#xff0c;我们可能会遇到寻找WiFi的情况&#xff0c;共享WiFi逐渐成为人们越来越常用的网络连接方式&#xff0c;随着共享WiFi服务商的不断增多&#xff0c;创业者如何如何挑选和判断哪家共享Wi…

金融考研人通向成功的快速通道——中国人民大学与加拿大女王大学金融硕士

在金融行业中&#xff0c;有这样一个中外合作办学硕士&#xff0c;它成为了很多金融考研人通向成功的快速通道。它免全国联考&#xff0c;学制一年&#xff0c;无英语要求&#xff0c;看到这里&#xff0c;王老师壹柒叁壹陆壹久领悟刘玲&#xff0c;很多同学是不是已经猜到了&a…

PNG转EPS,包括Latex导入

在电脑TEXLIVE文件夹里中找到bmeps.exe TEXLIVE\2022\bin\win32 可以新建一个文件夹picture&#xff08;图片和exe文件必须在一个文件夹里&#xff09;&#xff0c;将bmeps.exe复制出来&#xff0c;方便后续大量图片操作 导入png图片 新建一个txt文件&#xff0c;命名为Fig1.…

php74 安装sodium

下载编译安装libsodium wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable.tar.gz tar -zxf libsodium-1.0.18-stable.tar.gz cd libsodium-stable ./configure --without-libsodium make && make check sudo make install下载编译安装…

【Redis】高效保障MySQL和Redis的数据一致性?

高效保障MySQL和Redis的数据一致性? 在满足实时性的条件下,不存在两者完全保存一致的方案,只有最终一致性方案。根据网上的众多解决方案,总结出 6 种,直接看目录: 不好的方案 1、先写 MySQL,再写 Redis 如图所示: 这是一副时序图,描述请求的先后调用顺序; 橘黄…

Macos数据库管理:Navicat Premium 中文

Navicat Premium提供了直观且易用的图形用户界面&#xff0c;使得操作更为便捷。Navicat Premium 中文支持多种数据库系统&#xff0c;如MySQL、MariaDB、Oracle、SQLite、PostgreSQL等&#xff0c;可以让用户在同一平台上管理不同类型的数据库。Navicat Premium拥有强大的数据…

BUUCTF学习(四): 文件包含tips

1、介绍 2、hackBar插件安装 教程&#xff1a; Hackbar插件安装-CSDN博客 3、解题 php://filter/readconvert.base64-encode/resource要读取的文件 ?filephp://filter/readconvert.base64-encode/resourceflag.php Base64 在线编码解码 | Base64 加密解密 - Base64.us 结束

剑指offer(C++)-JZ50:第一个只出现一次的字符(算法-其他)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 在一个长为 字符串中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1&#xff08;需要区分…

传统鞋业焕发智造魅力,健康鞋步力宝品牌数字化转型助力多方把控

随着经济环境的变化以及市场竞争的加剧&#xff0c;加之我国劳动力、土地以及资源环境成本的快速上升&#xff0c;以劳动密集型为主、通过低附加值方式发展的传统产业集群遭遇瓶颈。而数字化时代的到来&#xff0c;不仅给各行各业带来了巨大的变革&#xff0c;也为传统鞋服业带…

王兴投资5G小基站

边缘计算社区获悉&#xff0c;近期深圳佳贤通信正式完成数亿元股权融资&#xff0c;本轮融资由美团龙珠领投。本轮融资资金主要用于技术研发、市场拓展等&#xff0c;将进一步巩固和扩大佳贤通信在5G小基站领域的技术及市场领先地位。 01 佳贤通信是什么样的公司&#xff1f; 深…

BIO实战、NIO编程与直接内存、零拷贝深入剖析

原生 JDK 网络编程 BIO BIO&#xff0c;意为 Blocking I/O&#xff0c;即阻塞的 I/O。   BIO 基本上就是我们上面所说的生活场景的朴素实现。在 BIO 中类 ServerSocket 负责绑定 IP 地址&#xff0c;启动监听端口&#xff0c;等待客户连接&#xff1b;客户端 Socket 类的实例…

倍福TwinCAT3.0软件与C++通讯问题(EAP通讯)

文章目录 一. TwinCAT控制器之间的几种通讯方式1.添加EAP设备2.添加变量刷新的Task周期3. 测试 一. TwinCAT控制器之间的几种通讯方式 协议硬件要求实时性说明ADS通讯普通网卡&#xff0c;支持无线典型值&#xff1a;< 100msServer/Client&#xff0c;要写 PLC 程序&#x…

全志R128芯片应用开发案例——ADC驱动烟雾传感器

ADC驱动烟雾传感器 本文案例代码下载地址ADC驱动烟雾传感器案例代码https://www.aw-ol.com/downloads?cat24 原理介绍 MQ-2型烟雾传感器属于二氧化锡半导体气敏材料&#xff0c;属于表面离子式N型半 导体。当处于200、300℃温度时&#xff0c;二氧化锡吸附空气中的氧&#…

网络端口验证

网络端口连通性验证 1、背景2、目标3、环境4、部署4.1、准备工作4.2、安装4.3、场景测试 1、背景 在日常运维过程中经常会遇到以下两种场景&#xff1a; 1、程序业务端口的开具及验证 2、业务程序访问异常网络排障 2、目标 1、验证端口的正确开具 2、网络策略的连通性 3、环…

onlyoffice的介绍搭建、集成过程。Windows、Linux

文章目录 什么是onlyoffice功能系统要求安装必备组件 windows搭建资源下载安装数据库onlyoffice安装测试 Linux搭建dockerdocker-compose 项目中用到的技术&#xff0c;做个笔记哈~ 什么是onlyoffice 在本地服务器上安装ONLYOFFICE Docs Community Edition Community Edition…

day06-前后端项目上传到gitee、后端多方式登录接口、发送短信功能、发送短信封装、短信验证码接口、短信登录接口

1 前后端项目上传到gitee 2 后端多方式登录接口 2.1 序列化类 2.2 视图类 2.3 路由 3 发送短信功能 4 发送短信封装 4.0 目录结构 4.1 settings.py 4.2 sms.py 5 短信验证码接口 6 短信登录接口 6.1 视图类 6.2 序列化类 1 前后端项目上传到gitee # 我们看到好多开源项目…