【C++】C++入门 类与对象(一)
类与对象(一)
- 一、类的引入
- 二、类的定义
- 1、类的两种定义方式:
- 2、成员变量命名规则的建议:
- 三、类的访问限定符及封装
- 1、访问限定符
- 2、封装
- 四、类的实例化
- 1、类的实例化概念
- 2、类对象的大小的计算
- 五、this指针
- this指针的特性
一、类的引入
在C语言结构体中只能定义变量,但是在C++中,结构体内不仅可以定义变量,也可以定义函数。比如:
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef int DataType;
struct Stack
{void Init(int _capacity=4)//缺省参数{DataType* tmp = (DataType*)malloc(sizeof(DataType) * _capacity);if (nullptr == tmp){perror("malloc fail:");exit(-1);}_a = tmp;_Top = 0;_capacity = _capacity;}DataType* _a;int _Top;int _capacity;
};
int main()
{Stack s1; //C++中struct定义的结构创建变量时不需要加structs1.Init(10);s1._Top = 100;s1._capacity = 200;return 0;
}
上面结构体的定义,在C++中更喜欢用class
来代替struct
。
二、类的定义
类的定义格式为:
class className
{
// 类体:由成员函数和成员变量组成
}; // 一定要注意后面的分号
class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。
类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。
1、类的两种定义方式:
- 声明和定义全部放在类体中(如类的引入中的代码),需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
- 类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用 ::作用域操作符指明成员属于哪个类域,因此成员函数名前需要加类名 ::,一般情况下,更期望采用此种方式。
头文件:Test.h中
函数实现:Test.cpp中
主函数文件:2023.02.07.cpp中
2、成员变量命名规则的建议:
先看一个错误示范:
class Date
{void Init(int year){// 这里的year到底是成员变量,还是函数形参?year = year;}int year;
};
实际上 = 号两边都是形参,因为局部变量优先,这里我们可以看出命名的重要性,为了避免与形参混淆,我们通常对成员变量前加一个"_"符号。
class Date
{void Init(int year){_year = year;}int _year;
};
三、类的访问限定符及封装
1、访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
访问限定符的使用:
class Stack
{
public:void Init(int _capacity = 4);
private:DataType* _a;int _Top;int _capacity;
};
【访问限定符说明】
- public修饰的成员在类外可以直接被访问
- protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
- 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
- 如果后面没有访问限定符,作用域就到} 即类结束。
- class的默认访问权限为private,struct为public(因为struct要兼容C,C的struct是公有的)
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定
#include"Test.h"
int main()
{Stack s1;s1.Init(10);//编译成功s1._Top = 100;//编译报错,无法访问return 0;
}
【面试题】
问题:C++中struct和class的区别是什么?
解答:C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类默认访问权限是private。
注意:在继承和模板参数列表位置,struct和class也有区别,后序给大家讲解。
2、封装
面向对象的三大特性:封装、继承、多态。
在类和对象阶段,主要是研究类的封装特性,那什么是封装呢?
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
封装本质上是一种管理,让用户更方便使用类。
例如:对于电脑这样一个复杂的设备,提供给用户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。
对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的,CPU内部是如何设计的等,用户只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可。
在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。
再例如,我们使用C++实现栈与C语言实现栈进行对比:
- C语言实现栈:
#include<stdio.h>
...
typedef int DataType;
typedef struct Stack
{DataType* a;int capacity;int Top;
}Stack;
void StackInit(Stack* ps){assert(ps);...;
}
void StackPush(Stack* ps, DataType data){assert(ps);...;
}
void StackPop(Stack* ps){assert(ps);...;
}........
int main()
{Stack s1;StackInit(&s);StackPush(&s, 3);StackDestroy(&s);return 0;
}
- C++实现栈
#include<iostream>
using namespeace std;
...
typedef int DataType;
class Stack
{
public:void Init(Stack* ps) {assert(ps);...;}void Push(Stack* ps, DataType data) {assert(ps);...;}void Pop(Stack* ps) {assert(ps);...;}........
private:DataType* a;int capacity;int Top;
};int main()
{Stack s1;Stack.Init(&s);Stack.Push(&s, 3);Stack.Destroy(&s);return 0;
}
对比就会发现C语言可以随便访问数据结构本身,容易造成安全问题,而C++只允许使用成员函数来访问数据结构本身,避免了这样的安全性问题,而且使用起来更加简单方便。
C++把栈中用到的所有函数和变量放在一起,对外封装成一个类,这也是封装的一种体现。
四、类的实例化
1、类的实例化概念
我们在类中定义的变量其实是变量声明,与函数声明类似,在定义类时操作系统并不会给我们开辟空间,只有我们用类去定义对象时,操作系统才会给我们开辟空间,用类类型创建对象的过程,我们称为类的实例化。
我们可以将类比作建筑图纸,别墅就是建筑图纸的实例化,那么对象就是类的实例化。
class test
{int a;//变量的声明int b;//变量的声明
};
int main()
{test t1;//用test类实例化了一个t1的对象return 0;
}
2、类对象的大小的计算
一个类可以实例化出多个对象,实例化出的对象 占用实际的内存空间,存储成员变量,那么我们如何计算类的大小呢?
废话少说,这里我们C++类的大小继承了C语言结构体大小的计算,也是按照结构体内存对齐规则
【结构体内存对齐规则】
- 第一个成员在与结构体偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的对齐数为8
- 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
请你计算一下32位平台下Date类的大小
class Date
{
public:void print(){cout<<_year<<"/"<<_month<<"/"<<_day<<"/"<<endl;}
private:int _year;int _month;int _day;
};
正确答案是:12,三个变量的对齐数都是4,类的最大对齐数为4,从前到后中间没有多余空间依次排列,故为12。
你可能会说,为什么不是16呢?函数print用一个函数指针存储起来而且32位平台下一个函数指针刚好占用4个字节。能想出这个问题说明你对函数指针学习的很好,但是呢我首先明确告诉你在C++的类中,类的大小只计算成员变量,不计算成员函数,再其次我们来讨论为什么C++的类中不计算成员函数的大小?
我们看下面一段代码,我们调用的两个函数Init()是不是同一个函数呢?
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;Date d2;d1.Init(2023, 2, 9);d2.Init(2023, 2, 10);return 0;
}
答案是是的,我们调用的是同一个函数,如果我们把成员函数也算进类的大小中,那么我们每次创建每个对象时都要为函数指针分配空间,当我们创建许多对象时,它们调用函数时都用同一个地址都要去调用同一个函数,但是呢,每个对象要有一个指针存储去存放相应函数地址,这就造成了一个函数的地址被许多个指针存储,内存空间造成了很大的浪费。
于是我C++就把成员函数全部放进一个叫公共区域,这个公共区域叫中叫做代码段,那个对象调用函数就去代码段中找相应的函数。
扩展知识:(可以忽略)
C/C++程序内存分配的几个区域:
- 栈区(stack):在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结
束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是
分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返
回地址等。 - 堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。分
配方式类似于链表。 - 数据段(静态区)(static)存放全局变量、静态数据。程序结束后由系统释放。
- 代码段:存放函数体(类成员函数和全局函数)的二进制代码。
有了上面的知识后我们再计算两个类的大小
// 类中仅有成员函数
class A2 {
public:void f2(){}
};
// 类中什么都没有---空类
class A3
{
};
你可能认为它们是0,但是那也太奇怪了吧?定义一个对象但是对象不占用内存???
其实这种类中仅有成员函数或类中什么都没有的空类,都是比较特殊的,编译器给了这种类一个字节来唯一标识这个类的对象。
五、this指针
this
是C++ 63个关键字中的一个。
对于它的理解我们先看一段代码
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(2022, 1, 11);d2.Init(2022, 1, 12);d1.Print();d2.Print();return 0;
}
对于上述类,有这样的一个问题:
Date类中有 Init()与 Print() 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?
首先我们知道如果我们是C语言实现这段代码的同样功能,在我们调用Init()与 Print() 函数时会采用传指针的方式,这个指针就可以帮我们区分不同的对象。
typedef struct Date
{int _year; // 年int _month; // 月int _day; // 日
}Date;
void Init(Data*pd,int year, int month, int day)
{pd->_year = year;pd->_month = month;pd->_day = day;
}
void Print(Data*pd)
{cout <<pd-> _year << "-" << pd->_month << "-" << pd->_day << endl;
}
int main()
{Date d1, d2;Init(&d1,2022, 1, 11);Init(&d2,2022, 1, 12);Print(&d1);Print(&d2);return 0;
}
与C语言不同的是C++中通过引入this
指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
上面的标准回答翻译成大白话就是:C++的实现原理与C语言一样,对象d1调用函数的话,this
指针就存储d1的地址,在传递参数时只不过我们不用自己传递指针了,是由编译器自动帮我们传递了指针。
C++实现的真实方式:
class Date
{
public:void Init(Date*this,int year, int month, int day)//此处只是为了演示,Date*this不用我们手动传递,//编译器会自动传递,我们手动传递会报错{this->_year = year;//此处的this->可以省略this->_month = month;//此处的this->可以省略this->_day = day;//此处的this->可以省略}void Print()//同理,不再演示{cout << _year << "-" << _month << "-" << _day << endl;}private:int _year; // 年int _month; // 月int _day; // 日
};
int main()
{Date d1, d2;d1.Init(2022, 1, 11);d2.Init(2022, 1, 12);d1.Print();d2.Print();return 0;
}
this指针的特性
- this指针的类型:类型* const,即成员函数中,不能给this指针赋值。
- 只能在“成员函数”的内部使用
- this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参,所以对象中不存储this指针。
- this指针是“成员函数”第一个隐含的指针形参,一般存在与栈中(因为它的本质是函数形参),VS通过ecx寄存器存储。
相关文章:
【C++】C++入门 类与对象(一)
类与对象(一)一、类的引入二、类的定义1、类的两种定义方式:2、成员变量命名规则的建议:三、类的访问限定符及封装1、访问限定符2、封装四、类的实例化1、类的实例化概念2、类对象的大小的计算五、this指针this指针的特性一、类的…...
笔记_js运算符
目录二进制相关运算符移位运算符<<>>|(位或运算)参考文档二进制相关运算符 移位运算符 移位运算就是对二进制进行有规律的移位。 tips:进制转换文档链接 << “<<”运算符执行左移位运算。在移位运算过程中,符号位始终保持不变…...
java面试题(十九) Mybatis
4.1 谈谈MyBatis和JPA的区别 参考答案 ORM映射不同: MyBatis是半自动的ORM框架,提供数据库与结果集的映射; JPA(默认采用Hibernate实现)是全自动的ORM框架,提供对象与数据库的映射。 可移植性不同&…...
Linux系统位运算函数以及相应CPU ISA实现收录
以32位数据的二进制表示为例,习惯的写法是LSB在左,MSB在右,注意BIT序和大小端的字节序没有关系。Linux和BIT操作有关的接口在定义在头文件bitops.h中,bitops.h定义有两层,通用层和架构层,对应两个bitops.h&…...
logback配置文件---logback.xml
目录常识操作logback-spring.xml 示例参考于 https://blog.csdn.net/white_ice/article/details/85065219 https://blog.csdn.net/weixin_42592282/article/details/122109703 https://www.dianjilingqu.com/629077.html 常识 https://www.dianjilingqu.com/629077.html nod…...
Web前端-设计网站公共header
设计网站公共headerheader元素是一个具有引导和导航作用的结构元素,很多企业网站中都有一个非常重要的header元素,一般位于网页的开头,用来显示企业名称、企业logo图片、整个网站的导航条,以及Flash形式的广告条等。在本网站中&am…...
引用和指针傻傻分不清
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀 目录 🐰引用和指针的区别 🌸从现象上看 🌸从编译上看 &am…...
MySQL面试题:关系型数据库SQL和非关系型数据库NoSQL
文章目录一、四大非关系型数据库与关系型数据库的对比1. 关系型数据库2. 基于列的数据库3. 键值对存储4. 文档存储5. 图形数据库参考文章(金文):四大非关系型数据库类型,你知道多少 参考文章:“行式存储”和“列式存储…...
1.Redis【介绍与安装】
1.常用数据库介绍 mysql的表类型[表引擎.存储引擎],memory表结构和表数据分开存储的,表结构保存在硬盘中,表数据保存在内存中memcache是一款软件,可以使用键值对的格式保存数据到内存中redis是意大利的工程师开发的开源免费的告诉缓存数据库,需要注意的是作者本身只开发了linu…...
DataStore快速上手1-preference
DataStore 概念 DataStore 可以存储两种类型的数据,一种是 preference,一种是 protobuf 每个进程在同一时间内仅能打开一个 DataStore 实例(或者通过其他管理手段来实现多个 DataStore 交替使用) 一个 DataStore 可以视为一张数…...
彻底掌握 MySQL InnoDB 的锁机制
本文是对沈剑大佬锁机制十多篇文章的概括总结,文末有全部链接,还参考了 10 多位其他网友的优秀分享。 1、概要 MySQL 中的锁可以按照粒度分为锁定整个表的表级锁(table-level locking)和锁定数据行的行级锁(row-level locking): 表级锁具有开…...
C++继承
1.继承的概念及定义 1.1继承的概念 继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构&#x…...
动态代理是基于什么原理?
第6讲 | 动态代理是基于什么原理? 编程语言通常有各种不同的分类角度,动态类型和静态类型就是其中一种分类角度,简单区分就是语言类型信息是在运行时检查,还是编译期检查。 与其近似的还有一个对比,就是所谓强类型和弱…...
YOLO-V4经典物体检测算法介绍
在前文我们介绍了YOLO-V1~V3版本都做了哪些事,本文我们继续介绍YOLO-V4版本。YOLO的作者在发表完V3之后,发现YOLO产品被美国军方应用到了很多军事战争当中,这是他所不希望看见的,因此宣布不再继续研究。但历史和科技总是随时间不断…...
angular相关知识点总结
创建 angualr 组件和传值 angular组件其实就是个xxx.component.ts,本质还是ts文件一个html文件 1.创建组件:在Angular中,可以使用命令行工具ng generate component创建一个新组件。例如: ng generate component my-component这将创建一个名…...
大坝安全监测系统:水库“守坝人”!
一、项目背景 随着社会经济的迅速发展,我国水资源利用率越来越高,各类水利水电工规模进一步扩大。在抗洪救灾、水利发电等方面带来巨大的经济和社会效益。但受多种因素影响,大坝的安全问题日益严重。大量工程实践证明,为保证大坝…...
CentOS7安装配置OpenVNP连接远端服务器
在项目当中需要访问一个三方接口及数据库,但是需要在CentOS7服务器上先配置OpenVPN,然后才能连接,现将整体配置过程记录如下。 安装 yum -y install epel-release yum -y install openvpn 查看版本 openvpn --version 配置客户端证书 打开…...
04- Matplotlib数据可视化详解 (数据库)
Matplotlib的亮点: import matplotlib.pyplot as plt # 导包plt.figure(figsize (9, 6) , 设置图片大小plt. plot(x, y), 画图绘制网格线: 线型, 颜色, 透明度plt.grid(linestyle --, color green, alpha0.75) # linestyle: 样式, color: 颜色, alpha: 透明度plt.axis(…...
高性能MySQL -- 查询性能优化
一般来说一个好的程序:查询优化,索引优化,库表结构要同时进行优化。今天我们来讲一下查询优化。 我们需要对MySQL的架构有基本认知,所以这里贴一张图大家看看: 图片来自于《小林coding》 为什么从查询会慢࿱…...
Android Binder机制之一(简介)
目录 前言 一、Android 进程间通信方式 二、Binder架构图 三、Binder涉及角色 3.1 Binder驱动 3.2 Binder实体 3.3 Binder引用 3.4 远程服务 3.5 ServiceManager守护进程 四、涉及源码 前言 这是本人第N次看Binder 相关知识了,其实每次看都有新的收获&…...
《SOC芯片研究框架》深度科普,发展趋势、技术特点、产业链一文看懂
片上系统SoC(System on Chip),即在一块芯片上集成一整个信息处理系统,简单来说 SoC芯片是在中央处理器CPU的基础上扩展音视频功能和专用接口的超大规模集成电路,是智能设备的“大脑”。随着半导体工艺的发展࿰…...
WebRTC中的ICE
ICE简介 ICE是用于UDP媒体传输的NAT穿透协议(适当扩展也可以支持TCP),它需要利用STUN和TURN协议来完成工作。 STUN协议提供了获取一个内网地址对应的公网地址映射关系(NAT Binding)的机制,并且提供了它们…...
了解webpack
文章目录一、webpack是什么?二、为什么要使用webpack三、webpack的五个核心概念四、安装webpack提示:以下是本篇文章正文内容,下面案例可供参考 一、webpack是什么? 本质上,webpack 是一个用于现代 JavaScript 应用程…...
NoSQL数据库详细介绍
一、NoSQL发展历史 NoSQL 一词最早出现于 1998 年,是 Carlo Strozzi 开发的一个轻量、开源、不提供 SQL 功能的关系数据库。 2009 年,Last.fm 的 Johan Oskarsson 发起了一次关于分布式开源数据库的讨论,来自 Rackspace 的 Eric Evans 再次…...
【2023】华为OD机试真题Java-题目0210-优秀学员统计
优秀学员统计 题目描述 公司某部门软件教导团正在组织新员工每日打卡学习活动,他们开展这项学习活动已经一个月了,所以想统计下这个月优秀的打卡员工。 每个员工会对应一个id,每天的打卡记录记录当天打卡员工的id集合,一共30天。 请你实现代码帮助统计出打卡次数top5的员…...
2023备战金三银四,Python自动化软件测试面试宝典合集
马上就又到了程序员们躁动不安,蠢蠢欲动的季节~这不,金三银四已然到了家门口,元宵节一过后台就有不少人问我:现在外边大厂面试都问啥想去大厂又怕面试挂面试应该怎么准备测试开发前景如何面试,一个程序员成长之路永恒绕…...
2023年实体店做什么比较好赚钱?
2023年实体店做什么比较好赚钱?未来实体店真正能赚的模型是什么?#百收#狂潮老师#千行#干货分享#商业思维 2023年实体店做什么比较好赚钱?...
SpringSecurity前后端分离(一篇就够了)
SpringSecurity前后端分离 从上至下操作,直接上手SpringSecurity 文章目录SpringSecurity前后端分离1、项目环境maven依赖数据库表2、自定义UserService接口3、屏蔽Spring Security默认重定向登录页面以实现前后端分离功能1、实现登录成功/失败、登出处理逻辑1、表…...
Allegro如何用Label Tune功能自动调整丝印到器件中心
Allegro如何用Label Tune功能自动调整丝印到器件中心 在做PCB设计的时候,调整丝印是比较费时的工作,如果需要把整板的丝印位号调整到器件的中心做装配图使用,Allegro的Label Tune功能支持快速把丝印位号居中到器件中心。 以下图为例,快速把所有丝印位号居中 调整前 调整后…...
Linux(十)线程安全 上
目录 一、概念 二、互斥锁实现互斥 三、条件变量实现同步 银行家算法 生产者与消费者模型 一、概念 概念:在多线程程序中,如果涉及到了对共享资源的操作,则有可能会导致数据二义性,而线程安全就指的是,就算对共享…...
先做网站还是先域名备案/今日热点新闻事件及评论
在办公时同事之间需要协作,避免不了文档的来回发送,那么该如何保证文档的安全呢?WPS云办公为保障文档安全,提供了账号加密和密码加密两种文档加密保护方式,为您的文档保驾护航,远离泄露风险。一账号加密1.安…...
四川省的建设厅注册中心网站首页/搜索引擎调词工具
1.打开vmware软件,初始化画面中,点击“Create a New Virtual Machine 2.点击“Custom(自己定义)” 3.无需选择,直接Next(上面是选Workstation版本号的兼容性的,这里默觉得当前版本号8.0。之前版本号的不同在…...
基于工作过程的商务网站建设 网页制作/店铺推广怎么做
IOS 字典模型互转框架 MJExtension能做什么? MJExtension是一套字典和模型之间互相转换的超轻量级框架 MJExtension能完成的功能 字典(JSON) --> 模型(Model) 模型(Model) --> 字典&…...
网站more应该怎么做/自媒体135的网站是多少
msgServer集群(ms) 设计作用: 该服务主要提供客户端的接入服务。每个ms维护当前接入用户的用户状态和心跳,每个ms地位是对等的。 设计考虑: ms之间不会直接交互,减少交互的复杂度。在用户数量增大的情况&am…...
开发网站用什么工具做设计/如何在百度搜索到自己的网站
在java中,垃圾意味着未引用的对象。垃圾收集是自动回收运行时未使用内存的过程。 换句话说,它是一种销毁未使用对象的方法。它类似于,在C语言中使用free()函数,在C中使用delete()。 但是,在java中这些会自动执行。因此…...
网站做多久才有流量/企业网站制作多少钱
wifi网速测试是一款wifi网络测速工具,让你一键查看当前网络状态。wifi网速测试app中提供了一键测速的功能,可以让用户在app内一键查看当前网络的状态,从而为用户带来及时调整的便利。另外app中还提供了网络安全检测功能,但需要你观…...