C++之多继承

1.基础知识

1.1 类之间的关系

has-A,uses-A 和 is-A

has-A

包含关系,用以描述一个类由多个“部件类”构成。实现has-A关系用类成员表示,即一个类中的数据成员是另一种已经定义的类。
常和构造函数初始化列表一起使用

uses-A

一个类部分地使用另一个类。通过类之间成员函数的相互联系,定义友元函数友元类或对象参数传递实现。

is-A

机制称为继承。关系具有传递性,不具有对称性。

1.2 继承概念
万事万物都有继承
这里写图片描述

这里写图片描述

1.3 继承示例代码
这里写图片描述

注意:C++中的继承方式(public、private、protected)会影响子类的对外访问属性。

示例代码:

#include <iostream>
using namespace std;class Parent
{
public:void print(){a = 0;b = 0;cout<<"a"<<a<<endl;cout<<"b"<<b<<endl;}int b;
protected:
private:int a;
};//class Child : private Parent
//class Child :  protected Parent public
class Child :  public Parent
{
public:
protected:
private:int c;
};void main11()
{Child c1;//c1.c = 1;//err//c1.a = 2;//errc1.b = 3;c1.print();cout<<"hello..."<<endl;system("pause");return ;
}

1.4 重要说明

1、子类拥有父类的所有成员变量和成员函数
2、子类就是一种特殊的父类
3、子类对象可以当作父类对象使用
4、子类可以拥有父类没有的方法和属性

2.派生类的访问控制

派生类继承了基类的全部成员变量和成员方法(除了构造和析构之外的成员方法),但是这些成员的访问属性,在派生过程中是可以调整的。

2.1 单个类的访问控制
1、类成员访问级别(public、private、protected)
2、思考:类成员的访问级别只有public和private是否足够?

示例代码:

#include <iostream>
using namespace std;//public 修饰的成员变量 方法 在类的内部 类的外部都能使用
//protected: 修饰的成员变量方法,在类的内部使用 ,在继承的子类中可用 ;其他 类的外部不能被使用
//private: 修饰的成员变量方法 只能在类的内部使用 不能在类的外部//派生类访问控制的结论
//1 protected 关键字 修饰的成员变量 和成员函数 ,是为了在家族中使用 ,是为了继承
//2 项目开发中 一般情况下 是 public
//3class Parent
{
public:int a; //老爹的名字
protected:int b; //老爹的银行密码
private:int c; //老的情人
};//保护继承
class Child3 : protected Parent
{
public:
protected:
private:
public: void useVar(){a = 0; // okb = 0; // ok //b这这里 写在了子类Child3的内部  2看protected 3密码===>protected//c = 0; //err}
};void main()
{Child3 c3;//c3.a = 10; //err//c3.b = 20; //err//c3.c = 30;//err}//私有继承
class Child2 : private Parent
{
public:void useVar(){a = 0; //okb = 0; //ok//c = 0; // err}protected:
private:
};void main22()
{Child2 c2;//c1.a = 10; err//c2.b = 20; err//c3.b = 30;
}class Child : public Parent
{
public:void useVar(){a = 0; //okb = 0; //ok//c = 0; // err}protected:
private:
};/*
C++中的继承方式(public、private、protected)会影响子类的对外访问属性 判断某一句话,能否被访问1)看调用语句,这句话写在子类的内部、外部2)看子类如何从父类继承(public、private、protected)  3)看父类中的访问级别(public、private、protected)
*/
//共有继承 
void main21()
{Parent t1, t2;t1.a  = 10; //ok//t1.b = 20; //err//t2.c = 30 ; //errcout<<"hello..."<<endl;system("pause");return ;
}

2.2 不同的继承方式会改变继承成员的访问属性

1)C++中的继承方式会影响子类的对外访问属性

public继承
父类成员在子类中保持原有访问级别

private继承
父类成员在子类中变为private成员

protected继承
父类中public成员会变成protected
父类中protected成员仍然为protected
父类中private成员仍然为private

2)private成员在子类中依然存在,但是却无法访问到。不论种方式继承基类,派生类都不能直接使用基类的私有成员 。


3)C++中子类对外访问属性表

这里写图片描述

这里写图片描述

2.3 “三看”原则

C++中的继承方式(public、private、protected)会影响子类的对外访问属性
判断某一句话,能否被访问

1)看调用语句,这句话写在子类的内部、外部
2)看子类如何从父类继承(public、private、protected)
3)看父类中的访问级别(public、private、protected)

2.4 派生类类成员访问级别设置的原则
思考:如何恰当的使用public,protected和private为成员声明访问级别?
1、需要被外界访问的成员直接设置为public
2、只能在当前类中访问的成员设置为private
3、只能在当前类和子类中访问的成员设置为protected,protected成员的访问权限介于public和private之间。

示例代码:

//类的继承方式对子类对外访问属性影响#include <cstdlib>
#include <iostream>using namespace std;class A
{
private:int a;
protected:int b;
public:int c;A(){a = 0;      b = 0;      c = 0;}void set(int a, int b, int c){this->a = a;        this->b = b;        this->c = c;}
};
class B : public A
{
public:void print(){//cout<<"a = "<<a; //errcout<<"b = "<<b; //okcout<<"c = "<<endl; //ok}
};class C : protected A
{
public:void print(){//cout<<"a = "<<a; //errcout<<"b = "<<b; // okcout<<"c = "<<endl; //ok}
};class D : private A
{
public:void print(){//cout<<"a = "<<a; //errcout<<"b = "<<b<<endl;  //okcout<<"c = "<<c<<endl; // ok}
};int main()
{A aa;B bb;C cc;D dd;aa.c = 100;  //okbb.c = 100; // ok//cc.c = 100; // err 保护的//dd.c = 100;  // erraa.set(1, 2, 3); //okbb.set(10, 20, 30); //ok//cc.set(40, 50, 60); // err//dd.set(70, 80, 90);  //errbb.print(); //okcc.print(); //okdd.print(); ///**/system("pause");return 0;
}

3.继承中的构造和析构

3.1 类型兼容性原则
类型兼容规则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代。通过公有继承,派生类得到了基类中除构造函数、析构函数之外的所有成员。这样,公有派生类实际就具备了基类的所有功能,凡是基类能解决的问题,公有派生类都可以解决。类型兼容规则中所指的替代包括以下情况:

  • 子类对象可以当作父类对象使用
  • 子类对象可以直接赋值给父类对象
  • 子类对象可以直接初始化父类对象
  • 父类指针可以直接指向子类对象
  • 父类引用可以直接引用子类对象
  • 在替代之后,派生类对象就可以作为基类的对象使用,但是只能使用
    基类继承的成员。
  • 类型兼容规则是多态性的重要基础之一。

总结:子类就是特殊的父类 (base *p = &child;)

#include <iostream>
using namespace std;class Parent
{
public:void printP(){cout<<"我是爹..."<<endl;}Parent(){cout<<"parent构造函数"<<endl;}Parent(const Parent &obj){cout<<"copy构造函数"<<endl;}private:int a;
};class child : public Parent
{
public:void printC(){cout<<"我是儿子"<<endl;}
protected:
private:int c;
};/*
兼容规则中所指的替代包括以下情况:子类对象可以当作父类对象使用子类对象可以直接赋值给父类对象子类对象可以直接初始化父类对象父类指针可以直接指向子类对象父类引用可以直接引用子类对象*///C++编译器 是不会报错的 .....
void howToPrint(Parent *base)
{base->printP(); //父类的 成员函数 }void howToPrint2(Parent &base)
{base.printP(); //父类的 成员函数 
}
void main()
{//Parent p1;p1.printP();child c1;c1.printC();c1.printP();//赋值兼容性原则 //1-1 基类指针 (引用) 指向 子类对象Parent *p = NULL;p = &c1;p->printP();  //1-2 指针做函数参数howToPrint(&p1);howToPrint(&c1); //1-3引用做函数参数howToPrint2(p1);howToPrint2(c1); //第二层含义//可以让子类对象   初始化   父类对象//子类就是一种特殊的父类Parent p3 = c1;cout<<"hello..."<<endl;system("pause");return ;
}

3.2 继承中的对象模型

  • 类在C++编译器的内部可以理解为结构体
  • 子类是由父类成员叠加子类新成员得到的
    这里写图片描述

这里写图片描述

问题:如何初始化父类成员?父类与子类的构造函数有什么关系

  • 在子类对象构造时,需要调用父类构造函数对其继承得来的成员进行初始化
  • 在子类对象析构时,需要调用父类析构函数对其继承得来的成员进行清理
#include <cstdlib>
#include <iostream>
using namespace std;class Parent04
{
public:Parent04(const char* s){cout<<"Parent04()"<<" "<<s<<endl;}~Parent04(){cout<<"~Parent04()"<<endl;}
};class Child04 : public Parent04
{
public:Child04() : Parent04("Parameter from Child!"){cout<<"Child04()"<<endl;}~Child04(){cout<<"~Child04()"<<endl;}
};void run04()
{Child04 child;
}int main_04(int argc, char *argv[])
{run04();system("pause");return 0;
}

3.3 继承中的构造析构调用原则
1、子类对象在创建时会首先调用父类的构造函数
2、父类构造函数执行结束后,执行子类的构造函数
3、当父类的构造函数有参数时,需要在子类的初始化列表中显示调用
4、析构函数调用的先后顺序与构造函数相反

#include <iostream>
using namespace std;//结论
//先 调用父类构造函数 在调用 子类构造函数
//析构的顺序  和构造相反/*
1、子类对象在创建时会首先调用父类的构造函数2、父类构造函数执行结束后,执行子类的构造函数3、当父类的构造函数有参数时,需要在子类的初始化列表中显示调用4、析构函数调用的先后顺序与构造函数相反
*/class Parent
{
public:Parent(int a, int b){this->a = a;this->b = b;cout<<"父类构造函数..."<<endl;}~Parent(){cout<<"析构函数..."<<endl;}void printP(int a, int b){this->a = a;this->b = b;cout<<"我是爹..."<<endl;}
private:int a;int b;
};class child : public Parent
{
public:child(int a, int b, int c) : Parent(a, b){this->c = c;cout<<"子类的构造函数"<<endl;}~child(){cout<<"子类的析构"<<endl;}void printC(){cout<<"我是儿子"<<endl;}
protected:
private:int c;
};void playObj()
{child c1(1, 2, 3);
}
void main()
{//Parent p(1, 2);playObj();cout<<"hello..."<<endl;system("pause");return ;
}

3.4 继承与组合混搭情况下,构造和析构调用原则

  • 先构造父类,再构造成员变量、最后构造自己
  • 先析构自己,在析构成员变量、最后析构父类
#include <iostream>
using namespace std;class Object
{
public:Object(int a, int b){this->a = a;this->b = b;cout<<"object构造函数 执行 "<<"a"<<a<<" b "<<b<<endl;}~Object(){cout<<"object析构函数 \n";}
protected:int a;int b;
};class Parent : public Object
{
public:Parent(char *p) : Object(1, 2){this->p = p;cout<<"父类构造函数..."<<p<<endl;}~Parent(){cout<<"析构函数..."<<p<<endl;}void printP(int a, int b){cout<<"我是爹..."<<endl;}protected:char *p;};class child : public Parent
{
public:child(char *p) : Parent(p) , obj1(3, 4), obj2(5, 6){this->myp = p;cout<<"子类的构造函数"<<myp<<endl;}~child(){cout<<"子类的析构"<<myp<<endl;}void printC(){cout<<"我是儿子"<<endl;}
protected:char *myp;Object obj1;Object obj2;
};void objplay()
{child c1("继承测试");
}
void main()
{objplay();cout<<"hello..."<<endl;system("pause");return ;
}

3.5 继承中的同名成员变量处理方法
1、当子类成员变量与父类成员变量同名时
2、子类依然从父类继承同名成员
3、在子类中通过作用域分辨符::进行同名成员区分(在派生类中使用基类的同名成员,显式地使用类名限定符)
4、同名成员存储在内存中的不同位置
这里写图片描述

这里写图片描述

总结:同名成员变量和成员函数通过作用域分辨符进行区分

#include <iostream>
using namespace std;class A
{
public:int a;int b;
public:void get(){cout<<"b "<<b<<endl;}void print(){cout<<"AAAAA "<<endl;}
protected:
private:
};class B : public A
{
public:int b;int c;
public:void get_child(){cout<<"b "<<b<<endl;}void print(){cout<<"BBBB "<<endl;}
protected:
private:
};void main()
{B b1;b1.print(); b1.A::print();b1.B::print(); //默认情况system("pause");
}//同名成员变量
void main71()
{B b1;b1.b = 1; //b1.get_child();b1.A::b = 100; //修改父类的bb1.B::b = 200; //修改子类的b 默认情况是Bb1.get();cout<<"hello..."<<endl;system("pause");return ;
}

3.6 派生类中的static关键字
继承和static关键字在一起会产生什么现象哪?
理论知识

  • 基类定义的静态成员,将被所有派生类共享
  • 根据静态成员自身的访问特性和派生类的继承方式,在类层次体系中具有不同的访问性质 (遵守派生类的访问控制)
  • 派生类中访问静态成员,用以下形式显式说明:
    类名 :: 成员
    或通过对象访问 对象名 . 成员
    这里写图片描述

这里写图片描述

这里写图片描述

总结:
1> static函数也遵守3个访问原则
2> static易犯错误(不但要初始化,更重要的显示的告诉编译器分配内存)
3> 构造函数默认为private

#include <iostream>
using namespace std;//单例
class A
{A(){cout<<"A的构造函数"<<endl;}
public:/*static int a;int b;*/
public:/*void get(){cout<<"b "<<b<<endl;}void print(){cout<<"AAAAA "<<endl;}*/
protected:
private:
};//int A::a = 100; //这句话 不是简单的变量赋值 更重要的是 要告诉C++编译器 你要给我分配内存 ,我再继承类中 用到了a 不然会报错../*
class B : private A
{public:int b;int c;
public:void get_child(){cout<<"b "<<b<<endl;cout<<a<<endl;}void print(){cout<<"BBBB "<<endl;}
protected:
private:
};
*///1 static关键字 遵守  派生类的访问控制规则//2  不是简单的变量赋值 更重要的是 要告诉C++编译器 你要给我分配内存 ,我再继承类中 用到了a 不然会报错..//3 A类中添加构造函数 //A类的构造函数中   A的构造函数是私有的构造函数 ... //被别的类继承要小心....//单例场景 .... UMLvoid main()
{A a1;//a1.print();//B b1;// b1.get_child();system("pause");
}void main01()
{// B  b1;//b1.a = 200;system("pause");
}

4.多继承

4.1 多继承概念
一个类有多个直接基类的继承关系称为多继承

  • 多继承声明语法
    class 派生类名 : 访问控制 基类名1 , 访问控制 基类名2 , … , 访问控制 基类名n
    {
    数据成员和成员函数声明
    };
  • 类 C 可以根据访问控制同时继承类 A 和类 B 的成员,并添加自己的成员
    这里写图片描述
#include <iostream>
using namespace std;class Base1
{
public:Base1(int b1){this->b1 = b1;}void printB1(){cout<<"b1:"<<b1<<endl; }
protected:
private:int  b1;
};class Base2
{
public:Base2(int b2){this->b2 = b2;}void printB2(){cout<<"b2:"<<b2<<endl; }
protected:
private:int  b2;
};class B : public Base1, public Base2
{
public:B(int b1, int b2, int c): Base1(b1), Base2(b2){this->c = c;}void printC(){cout<<"c:"<<c<<endl; }
protected:
private:int c;
};void main()
{B b1(1, 2, 3);b1.printC();b1.printB1();b1.printB2();cout<<"hello..."<<endl;system("pause");return ;
}

4.2 多继承的派生类构造和访问

  1. 多个基类的派生类构造函数可以用初始式调用基类构造函数初始化数据成员
  2. 执行顺序与单继承构造函数情况类似。多个直接基类构造函数执行顺序取决于定义派生类时指定的各个继承基类的顺序。
  3. 一个派生类对象拥有多个直接或间接基类的成员。不同名成员访问不会出现二义性。如果不同的基类有同名成员,派生类对象访问时应该加以识别。

4.3 简单应用
这里写图片描述
这里写图片描述

4.4 虚继承
如果一个派生类从多个基类派生,而这些基类又有一个共同的基类,则在对该基类中声明的名字进行访问时,可能产生二义性
这里写图片描述
分析如下:
这里写图片描述

#include <iostream>
using namespace std;class B
{
public:int b;
protected:
private:};class B1 : virtual public B
{
public:int b1;};class B2 : virtual  public B
{
public:int b2;
};class C : public B1, public B2
{
public:int c;
};void main()
{C  c1;c1.b1 = 100;c1.b2 = 200;c1.c = 300;c1.b = 500; //继承的二义性 和 虚继承解决方案//c1.B1::b = 500;//c1.B2::b = 500;cout<<"hello..."<<endl;system("pause");return ;
}

小结:
1)如果一个派生类从多个基类派生,而这些基类又有一个共同
的基类,则在对该基类中声明的名字进行访问时,可能产生二义性
2)如果在多条继承路径上有一个公共的基类,那么在继承路径的某处汇合点,这个公共基类就会在派生类的对象中产生多个基类子对象
3)要使这个公共基类在派生类中只产生一个子对象,必须对这个基类声明为虚继承,使这个基类成为虚基类。
4)虚继承声明使用关键字 virtual

这里写图片描述
这里写图片描述
4.5 总结

  • 继承是面向对象程序设计实现软件重用的重要方法。程序员可以在已有基类的基础上定义新的派生类。
  • 单继承的派生类只有一个基类。多继承的派生类有多个基类。
  • 派生类对基类成员的访问由继承方式和成员性质决定。
  • 创建派生类对象时,先调用基类构造函数初始化派生类中的基类成员。 - 调用析构函数的次序和调用构造函数的次序相反。
  • C++提供虚继承机制,防止类继承关系中成员访问的二义性。
  • 多继承提供了软件重用的强大功能,也增加了程序的复杂性。

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

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

相关文章

聊一聊 cookie

我们看到的 cookie 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 我自己创建了一个网站&#xff0c;网址为http://ppsc.sankuai.com。在这个网页中我设置了几个cookie&#xff1a;JS…

const的用法,特别是用在函数后面

原文出处&#xff1a;http://blog.csdn.net/zcf1002797280/article/details/7816977

图解 Linux 安装 JDK1.8 、配置环境变量

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 到官网下载 JDK 1.8 https://www.oracle.com/technetwork/java/javase/downloads/index.html 2. 用 rz 命令把 jdk-8u191-linux-x6…

C++之纯虚函数和抽象类

纯虚函数和抽象类 1.基本概念 2.案例 #include <iostream> using namespace std;////面向抽象类编程(面向一套预先定义好的接口编程)//解耦合 ....模块的划分class Figure //抽象类 { public://阅读一个统一的界面(接口),让子类使用,让子类必须去实现virtual void get…

解决: -bash: $‘\302\240docker‘: command not found

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 我只是运行 一条很简单的启动容器的命令&#xff0c;多次执行都报错&#xff0c;报错如题&#xff1a; -bash: $\302\240docker: comma…

【汽车取证篇】GA-T 1998-2022《汽车车载电子数据提取技术规范》(附下载)

【汽车取证篇】GA-T 1998-2022《汽车车载电子数据提取技术规范》&#xff08;附下载&#xff09; GA-T 1998-2022《汽车车载电子数据提取技术规范》标准—【蘇小沐】 总结 公众号回复关键词【汽车取证】自动获取资源合集&#xff0c;如链接失效请留言&#xff0c;便于…

解决: Client does not support authentication protocol requested by server; consider upgrading MySQL

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 在服务器上把 mysql 装好后&#xff0c;运行起来。 2. navicat 死活连接不上&#xff0c;在网上查说是要改数据库账号、密码什么的&…

C++之STL理论基础

1.基本概念 STL&#xff08;Standard Template Library&#xff0c;标准模板库)是惠普实验室开发的一系列软件的统称。虽然主要出现在C中&#xff0c;但在被引入C之前该技术就已经存在了很长的一段时间。 STL的从广义上讲分为三部分&#xff1a;algorithm&#xff08;算法&am…

解决maven打包报错:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 一、报错经历&#xff1a; 今天使用eclipse通过maven install打war包的时候&#xff0c;出现了下图所示的错误 二、问题分析&#xff1a…

STL之Vector

1.简介 vector是将元素置于一个动态数组中加以管理的容器。可以随机存取元素&#xff08;支持索引值直接存取&#xff0c;用[]操作符或at()方法&#xff0c;还支持迭代器方式存取&#xff09;。   vector尾部添加或移除元素非常快速。但是在中部或头部插入元素或移除元素比…

解决 : Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 执行 maven install 命令报错如题&#xff1a; Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:comp…

Docker 镜像 重命名

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 镜像改名命令格式&#xff1a; # 命令格式&#xff1a;docker tag 镜像id 仓库&#xff1a;标签或&#xff1a;docker tag 旧镜…

Java蓝桥杯02——第二题集锦:生日蜡烛、星期一、方格计数、猴子分香蕉

第二题 生日蜡烛(结果填空) 某君从某年开始每年都举办一次生日party&#xff0c;并且每次都要吹熄与年龄相同根数的蜡烛。 现在算起来&#xff0c;他一共吹熄了236根蜡烛。 请问&#xff0c;他从多少岁开始过生日party的&#xff1f; 请填写他开始过生日party的年龄数。 注意&a…

解决:Error response from daemon: Get https://index.docker.io/v1/search?q=openjdkn=25: dial tcp: looku

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 我只是想查一个 mysql 镜像。执行命令&#xff1a; docker search mysql 。报错如下&#xff1a; Error response from daemon…

安装 Git ( Windows、linux、Mac)

安装 Git 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 是时候动手尝试下 Git 了&#xff0c;不过得先安装好它。有许多种安装方式&#xff0c;主要分为两种&#xff0c;一种是通过编…

STL之函数适配器

1.理论知识 2.常用函数适配器 标准库提供一组函数适配器&#xff0c;用来特殊化或者扩展一元和二元函数对象。常用适配器是&#xff1a; 1绑定器&#xff08;binder&#xff09;: binder通过把二元函数对象的一个实参绑定到一个特殊的值上&#xff0c;将其转换成一元函数对象…

pyqt5 + pyinstaller 制作爬虫小程序

环境:mac python3.7 pyqt5 pyinstaller ps: 主要是熟悉pyqt5, 加入了单选框 输入框 文本框 文件夹选择框及日历下拉框 效果图: pyqt5 主程序文件 # -*- coding: utf-8 -*- # Author: Mehaei # Date: 2019-07-10 13:02:56 # Last Modified by: Mehaei # Last Modified time…

axios中出现两次请求,OPTIONS请求和GET请求

在项目中发现ajax中出现两次请求&#xff0c;OPTIONS请求和GET请求 查看到浏览器NetWork有两次请求&#xff0c;请求url一样&#xff1a; 查找原因是浏览器对简单跨域请求和复杂跨域请求的处理区别。 XMLHttpRequest会遵守同源策略(same-origin policy). 也即脚本只能访问相同协…

Linux 安装 配置 Maven

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1.需要提前安装JDK&#xff0c;并且配置环境变量 请参考&#xff1a;https://blog.csdn.net/jiangyu1013/article/details/84321146 2.…

[Git高级教程 (一)] 通过 Tag 标签回退版本修复 bug

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1 前言 本系列之所以取名”Git高级教程”&#xff0c;主要是教大家解决实际工作中遇到的问题&#xff0c;要求读者会基本的Git用法和命令…