2023/9/8 -- C++/QT

news2024/11/28 8:33:03

作业

1> 自行封装一个栈的类,包含私有成员属性:栈的数组、记录栈顶的变量

成员函数完成:构造函数、析构函数、拷贝构造函数、入栈、出栈、清空栈、判空、判满、获取栈顶元素、求栈的大小

02stack.h:

#ifndef __02STACK_H__
#define __02STACK_H__
#include <iostream>

#define MAX 10      //栈的容量
using namespace std;

class Stack{
private:
    int *data;      //栈的数组
    int top;        //栈顶下标
public:
    //构造函数
    Stack();
    //析构函数
    ~Stack();
    //拷贝构造函数
    Stack(const Stack &other);
    //判空
    bool empty();
    //判满
    bool full();
    //入栈
    int push();
    //出栈
    int pop();
    //清空栈
    int clear();
    //获取栈顶元素
    int get_top_value();
    //求栈的大小
    int size();
};

#endif // 02STACK_H

02stack.cpp:

#include "02stack.h"

//构造函数
Stack::Stack():data(new int[MAX]),top(-1){      //栈顶从-1开始
    cout<<"初始化成功!"<<endl;
    //cout<<"构造函数"<<endl;
}
//析构函数
Stack::~Stack(){
    delete []data;
    //cout<<"析构函数"<<endl;
}
//拷贝构造函数
Stack::Stack(const Stack &other){
    top = other.top;
    data = new int[MAX];
    for(int i = 0;i <= top;i++){
        data[i] = other.data[i];
    }
    cout<<"拷贝成功!"<<endl;
    //cout<<"拷贝构造函数"<<endl;
}
//判空
bool Stack::empty(){
    return top == -1;
}
//判满
bool Stack::full(){
    return top >= MAX-1;
}
//入栈
int Stack::push(){
    if(full()){
        cout<<"栈满!入栈失败!"<<endl;
        return -1;
    }
    int value;
    cout<<"请输入您要入栈的元素:";
    cin>>value;
    top++;
    data[top] = value;
    cout<<value<<"  入栈成功!"<<endl;
    //cout<<"top = "<<top<<endl;
    return 0;
}
//出栈
int Stack::pop(){
    if(empty()){
        cout<<"栈空!出栈失败!"<<endl;
        return -1;
    }
    int temp = data[top];
    data[top] = 0;
    top--;
    cout<<temp<<"  出栈成功!"<<endl;
    return 0;
}
//清空栈
int Stack::clear(){
    data[top] = 0;
    while (top-->0) {
        data[top] = 0;
    }
    cout<<"清空栈成功!"<<endl;
    return 0;
}
//获取栈顶元素
int Stack::get_top_value(){
    cout<<"栈顶元素为:"<<data[top]<<endl;
    return 0;
}
//求栈的大小
int Stack::size(){
    cout<<"栈的大小为:"<<top+1<<endl;
    return 0;
}

 main.cpp:

#include "02stack.h"

int main()
{
    Stack s;
    s.push();
    s.push();
    s.push();
    s.get_top_value();
    s.size();
    Stack s1 = s;
    s1.size();
    s1.get_top_value();
    s.pop();
    s.clear();
    s.size();
    return 0;
}

效果图:

2> 自行封装一个循环顺序队列的类,包含私有成员属性:存放队列的数组、队头位置、队尾位置

成员函数完成:构造函数、析构函数、拷贝构造函数、入队、出队、清空队列、判空、判满、求队列大小

03queue.h:

#ifndef __03QUEUE_H__
#define __03QUEUE_H__
#include <iostream>

#define MAX 10
using namespace std;

class Queue{
private:
    int front;
    int back;
    int *data;
public:
    //构造函数
    Queue();
    //析构函数
    ~Queue();
    //拷贝构造函数
    Queue(const Queue &other);
    //判空
    bool empty();
    //判满
    bool full();
    //入队
    int push();
    //出队
    int pop();
    //清空队列
    int clear();
    //求队列大小
    int size();
};

#endif // 03QUEUE_H

03queue.cpp:

#include "03queue.h"

//构造函数
Queue::Queue():front(0),back(0),data(new int[MAX]){
    cout<<"初始化成功"<<endl;
    cout<<"构造函数"<<endl;
}
//析构函数
Queue::~Queue(){
    delete []data;
    cout<<"析构函数"<<endl;
}
//拷贝构造函数
Queue::Queue(const Queue &other){
    front = other.front;
    back = other.back;
    data = new int[MAX];
    if(front < back){
        for(int i = front;i < back;i++){
            data[i] = other.data[i];
        }
    }
    if(front > back){
        for(int i = front;i < back+MAX;i++){
            data[i%MAX] = other.data[i%MAX];
        }
    }
    //cout<<"q1.front = "<<front<<endl;
    //cout<<"q1.back = "<<back<<endl;
    //cout<<"front = "<<other.front<<endl;
    //cout<<"back = "<<other.back<<endl;
    cout<<"拷贝构造函数"<<endl;
}
//判空
bool Queue::empty(){
    return front == back;
}
//判满
bool Queue::full(){
    return (back+1)%MAX == front;
}
//入队
int Queue::push(){
    if(full()){
        cout<<"队列已满!入队失败!"<<endl;
        return -1;
    }
    int value;
    cout<<"请输入您要入队的元素:";
    cin>>value;
    data[back] = value;
    back = (back+1)%MAX;
    //cout<<"front = "<<front<<endl;
    //cout<<"back = "<<back<<endl;
    cout<<value<<"  入队成功!"<<endl;
    return 0;
}
//出队
int Queue::pop(){
    if(empty()){
        cout<<"队列已空!出队失败!"<<endl;
        return -1;
    }
    int temp = data[front];
    data[front] = 0;
    front = (front+1)%MAX;
    //cout<<"front = "<<front<<endl;
    //cout<<"back = "<<back<<endl;
    cout<<temp<<"  出队成功!"<<endl;
    return 0;
}
//清空队列
int Queue::clear(){
    if(front < back){
        for(int i = front;i < back;i++){
            data[i] = 0;
        }
    }
    if(front > back){
        for(int i = front;i < back+MAX;i++){
            data[i%MAX] = 0;
        }
    }
    front = back = 0;
    //cout<<"front = "<<front<<endl;
    //cout<<"back = "<<back<<endl;
    cout<<"清空队列成功!"<<endl;
    return 0;
}
//求队列大小
int Queue::size(){
    cout<<"队列大小为:"<<(back+MAX-front)%MAX<<endl;
    return 0;
}

 main.cpp:

#include "03queue.h"

int main()
{
    Queue q;
    q.push();
    q.push();
    q.push();
    q.size();
    Queue q1 = q;
    q1.size();
    q.pop();
    q.pop();
    q.size();
    q.push();
    q.clear();
    return 0;
}

效果图:

一、类

1.1 类的定义格式

class 类名
{
    public:
        公共的成员变量、成员函数的定义;
    protected:
        受保护的成员变量、成员函数;
    private:
        私有的成员变量、成员函数;
};

//注意
1、类中是有访问权限控制
    public该权限下的成员,可以在类内、子类中、类外被访问
    protected该权限下的成员,可以在类内、子类中被访问,类外不能被访问
    private:该权限下的成员可以在类内被访问,子类中和类外都无权访问
2、类中的访问权限是针对于类体而言的,跟类对象没有关系
3、如果没有给定访问权限,默认是私有的访问权限
4、每个访问权限可以出现多次,可以出现在类内的任何位置,每种访问权限的作用域是从该关键字开始到下一个关键字或整个类体结束为止
5、我们通常将某个权限下的所有成员放到一个访问权限关键字下
6、通常成员属性一般定义成私有权限,成员函数一般定义成公有权限
7、类中的成员函数可以访问类中的任意权限下的成员,包括私有成员

1.2 类的大小

1> 一个空类的大小为1字节,起到占位作用,如果有成员属性,则会将这一字节分配给成员属性

2> 类的大小也跟结构体一样遵循字节对齐

3> 类中的普通成员函数不占类的大小,即使成员函数中有变量

4> 类中如果存在虚函数,那么会默认提供一个指针的大小(后期讲)

1.3 C++中结构体与类的区别

1> C++中结构体跟类没什么太大区别,主要的区别是默认访问权限和默认继承方式不同

2> C++中结构体的默认访问权限是public,而类的默认访问权限是private

3> C++中结构体的默认继承方式是public,而类的默认继承方式是private

4> 使用场景:一般实现数据结构的相关操作,我们使用结构体完成,其他有关类对象的实现,我们使用类来完成

二、this指针

2.1 引入目的

在类的定义过程中,有可能需要使用一个变量来指代类对象本身,用来找该类中的成员属性或成员变量,此时C++编译器会给类中所有非静态成员函数提供一个隐藏的形参指针this,表明指代该类本身,哪个对象使用我,我就指向哪个对象的起始地址。

2.2 this的原型推导

1> 原型:类名 * const this;

2> 可以通过this指针更改类中的内容,但是不能更改this的指向

3> 只有成员函数中才能使用this指针,是每个非静态成员函数都拥有的一个隐藏形参

2.3 必须使用this的场景

1> 当非静态成员函数中,函数的形参名或局部变量名与类的成员名同名时,在函数体内必须使用this指针加以区分,否则使用的是局部变量

2> 在拷贝赋值函数中,需要返回自身的引用时,需要使用this指针

三、类中特殊的成员函数

当定义一个类时,编译器会给类体提供一些特殊的函数。

特殊原因:如果没有显性定义这些函数,系统会默认提供这些函数,如果显性定义了这些函数,系统就不再提供默认的了

这些函数无需显性调用,特殊时期系统会自动调用

特殊函数:构造函数、析构函数、拷贝构造、拷贝赋值、移动构造、移动赋值、取地址运算符重载、常取地址运算符重载

3.1 构造函数

1> 功能:使用类实例化对象时,用于给类对象申请资源并初始化用的

2> 定义格式

1、函数名与类同名
2、没有返回值,连void都没有
3、权限:一般为public
4、参数:可以有也可以没有参数,构造函数可以重载
5、格式:
        类名(形参列表){函数体内容}

3> 调用时机

在使用类实例化对象过程中,系统自动调用该函数,无需手动调用

栈区:实例化对象时,系统自动调用构造函数

                类名 对象名(实参列表); //此时系统会自动调用构造函数

堆区:定义类对象指针时,不会调用构造函数,当使用new关键字给类对象申请空间时会自动调用构造函数

                类名 *指针名; //此时不会调用构造函数

                指针名 = new 类名(实参列表); //此时才会调用构造函数

4> 注意:

1、如果类内没有显性定义任何构造函数,系统会默认提供一个无参构造函数,

2、如果显性定义了任意一种有参构造函数,系统就不再提供无参构造函数了,如果非要使用无参构造函数,需要显性再定义出无参构造函数

3、 一个类中,可以定义多个构造函数,这多个构造函数构成重载关系

4、构造函数的也支持默认参数

#include <iostream>

using namespace std;
class Stu
{
private:
    string name;
    int age;
    double score;

public:
    //显性定义无参构造函数
    Stu()
    {
        cout<<"Stu::无参构造"<<endl;
    }

    Stu(string n)
    {
        name = n;           //给成员变量n进行赋值
        cout<<"Stu::一个参数的构造函数"<<endl;
    }

    //带默认参数的构造函数
    Stu(string n, int a, double s = 90)
    {
        name = n;
        age = a;
        score = s;
        cout<<"Stu::所有参数的构造函数"<<endl;
    }

    //定义成员函数
    void show()
    {
        cout<<"name = "<<name<<endl;
        cout<<"age = "<<age<<endl;
        cout<<"score = "<<score<<endl;
    }
};

int main()
{
    Stu s1;          //在栈区实例化一个学生对象
    s1.show();        //随机值

    cout<<"***************************************"<<endl;
    Stu *p1;          //不会调用构造函数
    p1 = new Stu;       //此时会调用构造函数
    p1->show();

    cout<<"***************************************"<<endl;
    Stu s2("zhangpp");
    s2.show();

    cout<<"***************************************"<<endl;
    Stu s3("zhangsan", 18);
    s3.show();

    return 0;
}

5> 构造函数可以设置初始化列表

1、使用格式:在构造函数的形参列表后,由冒号引出初始化列表,完成初始化工作

        类名(类型1 形参1, 类型2 形参2,。。。,类型n 形参n):成员1(形参1),成员2(形参2),。。。,成员n(参数n)

        {

                函数体内容;

        }

2、注意:在初始化列表中,括号内是形参数据,括号外是成员数据,不要写反

6> 构造函数必须使用初始化列表的情况

1、当类中的成员有引用成员时,必须在初始化列表中对该引用成员进行初始化

2、当类中有const修饰的成员变量时,对该成员的的初始化也必须放在初始化列表中

3、当构造函数的形参名和成员变量名同名时,可以使用初始化列表来解决初始化问题

4、当类中有其他类的对象作为成员变量时,对该类对象的初始化工作也必须在初始化列表中完成,需要在初始化列表中显性调用成员对象的有参构造完成初始化工作,如果没有显性调用成员对象的有参构造,系统会自动调用该成员对象的无参构造来完成对该成员对象的初始化工作

3.2 析构函数

1> 功能:在类对象消亡时,用于回收类对象的资源空间用的

2> 定义格式

1、函数名是在类名前加~:~类名
2、参数:无
3、返回值:没有
4、权限:一般为public
5、格式:
    ~类名(){}

3> 调用时机:

栈区:类对象的作用域结束时,系统会自动调用该类的析构函数,完成对对象的内存回收。

堆区:何时使用delete何时调用析构函数,一直不调用,一直不析构

4> 注意:

1、如果类中没有显性定义析构函数,系统会默认提供一个析构函数完成对成员内存的回收工作

2、如果类中显性定义了析构函数,系统就不再提供,默认的析构函数了

3、构造和析构的顺序:

        栈区:先构造的后析构,后构造的先析构(在同一作用域下)

        堆区:何时使用delete何时调用析构函数

4、如果类中没有指针成员,那么使用系统提供的析构函数就足够完成对类对象的内存回收

        如果类中有指针成员,并指向堆区空间,需要显性定义析构函数,在析构函数的函数体内,将成员指针指向的空间进行释放,否则会内存泄漏

5、一个类中析构函数只能有一个

3.3 拷贝构造函数

1> 拷贝构造函数是一个特殊的构造函数,功能是:使用一个类对象给另一个类对象初始化时,系统自动调用

                string s1("hello world"); //有参构造

                string s2 = s1; //调用拷贝构造

                string s3(s2); //拷贝构造函数

2> 定义格式

1、函数名与类同名
2、没有返回值
3、参数:同类的其他类对象的引用
4、权限:一般为public
5、格式:
    类名(const 类名 &other){}

3> 调用时机:

1、使用一个类对象给另一个类对象初始化时,系统自动调用

2、函数形参时类对象时,实参向形参传递时,也会调用拷贝构造函数

3、函数返回值是类对象时,函数调用时也会调用拷贝构造函数

4> 注意事项:

1、如果没有显性定义拷贝构造函数,系统会默认提供一个拷贝构造函数,来完成对象成员之间的简单赋值

2、如果显性定义了拷贝构造函数,系统就不再提供默认的拷贝构造函数了

5> 深浅拷贝

1、在一个类中,如果没有显性定义拷贝构造函数,系统会默认提供一个拷贝构造函数,来完成类对象之间的简单赋值,这个拷贝构造函数是一个浅拷贝,如果类中无指针成员,那么使用该拷贝构造函数没有问题

2、如果类中有指针成员并且指向堆区空间,使用浅拷贝就会造成对同一个堆区空间的多次释放问题,会产生double free的段错误

3、此时就需要显性定义拷贝构造函数完成深拷贝:在拷贝构造函数的初始化列表中,给自己的指针成员重新申请出一个空间,将原对象的指针成员指向的空间内容赋值过来,即可完成深拷贝

#include <iostream>

using namespace std;
class Stu
{
private:
    string name;
    int age;
    double score;

public:
    //显性定义无参构造函数
    Stu()
    {
        cout<<"Stu::无参构造"<<endl;
    }

    //带默认参数的构造函数
    Stu(string n, int a, double s ):name(n),age(a),score(s)
    {
        cout<<"Stu::有参构造函数"<<endl;
    }

    //定义析构函数
    ~Stu()
    {
       cout<<"Stu::析构函数:"<<this<<endl;
    }

    //定义拷贝构造函数
    Stu(const Stu &other):name(other.name), age(other.age), score(other.score)
    {
        cout<<"拷贝构造函数"<<endl;
    }

    //定义成员函数
    void show()
    {
        cout<<"name = "<<name<<endl;
        cout<<"age = "<<age<<endl;
        cout<<"score = "<<score<<endl;
    }
};


//定义一个全局函数,实参向形参传递时调用拷贝构造,函数返回时也会调用拷贝构造
Stu fun(Stu s)                 //int num = 520;
{
    s.show();
    return  s;
}

int main()
{
    Stu s1("zhangpp", 18, 90);         //调用有参构造函数

    fun(s1);

    return 0;
}

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

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

相关文章

​重生奇迹MU魔法师的装备属性​

魔法师的武器主要武器装备&#xff0c;主要分类为单手武器、双手武器、戒指、项链、盾牌、头盔、铠甲、护手、护腿、鞋子&#xff0c;玩家需要根据情况集齐这些装备。 智力果实以及体力果非常重要&#xff0c;在实战的时候非常实用。实获取途径一般是果实合成、宝藏&#xff0…

说说分布式系统容器化

继上一篇浅谈高并发分布式架构演进路径&#xff0c;单体服务完成分布式架构改造&#xff0c;转型为微服务。随着微服务数量的急剧增加&#xff0c;跨应用、跨系统的调用越来越多&#xff0c;调用关系和依赖关系日益复杂&#xff0c;这种复杂性增加了系统的设计、实施和维护的难…

Java并发基石——CAS是如何实现的?

目录 1. 什么是CAS&#xff1f; 2. Java中关于 CAS 的 API 在哪里&#xff1f; 3. CAS API方法和参数解析 4. CAS的底层实现 5. CAS是如何保证多核线程安全的&#xff1f; 6. CAS的缺点&#xff1f; 7. 如何避免ABA问题&#xff1f; 1. 什么是CAS&#xff1f; CAS的全程是…

动态库静态库对比

程序编译成可执行程序的过程 静态在连接阶段会把代码复制到可执行文件中 动态则不&#xff0c;而是打包一些信息进去&#xff0c;在执行的时候根据信息找到动态库执行 制作过程 静态库 动态库 优缺点 库比较小且更新慢的时候一般使用静态&#xff0c;反之则动态 静态库 …

七种 BeanDefinition,各显其能!

聚沙成塔&#xff01;不知不觉 Spring 源码已经连续更了两个月啦&#xff0c;视频也录制了不少了&#xff0c;对 Spring 源码分析感兴趣的小伙伴戳这里哦Spring源码应该怎么学&#xff1f;&#xff5e; 今天我们继续来看 Spring 源码中一个非常重要的概念&#xff1a;BeanDefi…

万物皆可连的腾讯轻联

文章目录 前言关于腾讯轻联小试牛刀新建流程配置逻辑组件配置连接器流程上线 其它功能核心能力总结 前言 工作中有这样一个需求&#xff0c;每周五下午三点定时给小组内成员发送邮件&#xff0c;邮件内容固定&#xff0c;主要作用是提醒大家记得发周报&#xff1b;其实这个需求…

iOS:解决Could not find a storyboard named ‘LaunchScreen.storyboard‘ in bundle NSBundle

打开项目的&#xff1a;HBuilder-uniPlugin-Info.plist 删除Launch screen interface file base name 然后看图&#xff0c;清空掉之前的LaunchScreen.storyboard东西 再运行就可以了&#xff0c;我也是改自定基座出的问题略

西门子LAD编程扫描周期带来的步序跳转问题

一、程序目的 按一下启动&#xff0c;程序进入第一步。延时五秒之后进入第二步进行自加1&#xff0c;然后回到第一步继续延时5秒循环&#xff0c;依次类推。 二、出现的问题 第一次程序进入第一步时&#xff0c;定时器正常定时&#xff0c;计数正常加1&#xff0c;但从第二轮开…

使用WinDbg进行动态调试

前言 本文章主要介绍如何使用WinDbg进行动态调试。如果程序崩溃后&#xff0c;没有记录dump文件&#xff0c;或者程序启动时发生异常&#xff0c;比如常见的 应用程序无法正常启动(0xc000007b) 报错&#xff0c;都可以使用WinDbg动态调试功能来定位问题。文章最后&#xff0c;…

用go实现一个循环队列

目录 队列数组队列的“假溢出”现象循环队列三种判断队列空和满的方法无下标&#xff08;链式&#xff09;有下标&#xff08;顺序&#xff09;长度标记 go用顺序表实现一个循环队列队列的链式存储结构 队列 队列&#xff08;queue&#xff09;是只允许在一端进行插入操作&…

物联网世界的无线电报之MQTT详解

文章目录 1. 前言1.1. 物联网与MQTT的关系1.2. MQTT的重要性及应用场景 2. MQTT基础2.1. MQTT的定义与起源2.2. MQTT的工作原理2.3. MQTT的协议格式2.4. 用java造个轮子 3. 深入理解MQTT3.1. MQTT的主要组件3.1.1. Publisher&#xff08;发布者&#xff09;3.1.2. Subscriber&a…

RTSP流媒体服务器EasyNVR视频平台以服务方式启动异常却无报错,该如何解决?

EasyNVR是基于RTSP/Onvif协议的安防视频云服务平台&#xff0c;可实现设备接入、实时直播、录像、检索与回放、云存储、视频分发、级联等视频能力服务&#xff0c;可覆盖全终端平台&#xff08;电脑、手机、平板等终端&#xff09;&#xff0c;在智慧工厂、智慧工地、智慧社区、…

【2023微博评论爬虫】用python爬上千条微博评论,突破15页限制!

文章目录 一、爬取目标二、展示爬取结果三、爬虫代码四、同步视频五、获取完整源码 您好&#xff0c;我是 马哥python说&#xff0c;一枚10年程序猿。 一、爬取目标 前些天我分享过一篇微博的爬虫&#xff1a; 马哥python说&#xff1a;【python爬虫案例】爬取微博任意搜索关…

【网络编程】IO多路复用

IO多路复用是一种高效的I/O处理方式&#xff0c;它允许单个进程能够同时监视多个文件描述符&#xff08;sockets、文件等&#xff09;&#xff0c;并在其中任何一个文件描述符准备好进行I/O操作时进行处理。它的核心在于使用少量的线程或进程来管理多个I/O操作&#xff0c;以提…

【JavaSpring】spring接口-beanfactory和applicationcontext与事件解耦

beanfactory 1.applicationcontext的父接口 2.是Spring的核心容器 功能 表面只有getBean&#xff0c;但实现类默默发挥了巨大作用 1.管理所有bean 2.控制反转 3.基本的依赖注入 applicationcontext 功能 1.继承了MessageSource&#xff0c;有了处理国际化资源的能力 …

【C++】继承基础知识一遍过

目录 一&#xff0c;概念 二&#xff0c;继承定义 1. 继承格式 2. 访问限定符与继承方式的关系 3. 继承父类成员访问方式的变化 小结&#xff1a; 三. 父类与子类对象赋值转化 四&#xff0c;继承作用域 1.特点 2. 测试题 五&#xff0c;派生类不一样的默认成员函…

【nacos】2.1.1持续输出事件警告日志

nacos-server 2.1.1 持续输出事件警告日志,修复NamingTraceEvent连续打印日志。这是 2.1.1 beta 功能跟踪事件。如果没有订阅者处理TraceEvent&#xff0c;将打印此日志。2.1.1版本中忽略它&#xff0c;我们将在2.1.2版本中对其进行增强。 WARN There are no [com.alibaba.nac…

Linux系统中驱动之设备树的platform驱动实现

每日一个简单的驱动&#xff0c;日久方长&#xff0c;对Linux驱动就越来越熟悉&#xff0c;也越来容易学会写驱动程序。今日进行设备树下的platform设备驱动。 前面一篇我们讲解了传统的、未采用设备树的 platform 设备和驱动编写方法。最新的 Linux 内核已经支持了设备树&…

c语言练习45:模拟实现内存函数memcpy

模拟实现内存函数memcpy 针对内存块&#xff0c;不在乎内存中的数据。 拷贝内容有重叠的话应用memmove 模拟实现&#xff1a; 代码&#xff1a; 模拟实现memcpy #include<stdio.h> #include<assert.h> void* my_memcpy(void* dest, const void* src, size_t num…

【计算机基础知识3】IP 地址和子网掩码、DNS、HTTP

目录 前言 一、IP地址和子网掩码 1. IP地址的概念 2. IP地址的分类 3. 子网掩码的概念 4. 子网掩码的用途 二、域名系统&#xff08;DNS&#xff09; 1. DNS的作用 2. 域名解析过程 3. 如何配置和管理域名解析 三、HTTP&#xff08;超文本传输协议&#xff09; 1. H…