1、基类与派生类

类的继承:面向对象的程序设计中提供了类的继承机制,允许程序员在保持原有类特性的基础上,进行更具体、更详细的定义

用途:代码的重用性(继承)和可扩充性(派生)

:植物大战僵尸游戏中,可以将普通僵尸作为一个基类,设计其他僵尸(路障僵尸,铁门僵尸等)

---------------------------------------

类的继承:新类从已有类得到特性(新类继承了已有类的特性)

类的派生:从已有类产生新类的过程(新类自身的新特性)

继承与派生是同一过程,只是观察角度不同

继承的目的:代码重用

派生的目的:为解决新问题,对原有程序进行改造

---------------------------------------

被继承的类称为基类父类

派生出的新类称为派生类子类

---------------------------------------

一个基类可派生出多个派生类

一个派生类可同时拥有多个基类

直接参与派生出某类的基类称为直接基类

基类的基类甚至更高层的基类称为间接基类

--------------------------------------

单继承可以看作是多继承的一个特例,多继承可以看成是多个单继承的组合

一个派生类可以同时有个基类,称为多继承

一个派生类可以同时有1个基类,称为单继承

2、 派生类

2.1 派生类介绍

派生类定义语法:

class 派生类名: 继承方式 基类名1, 继承方式 基类名2,...,继承方式 基类名n
{
派生类成员声明;
};
//例:
//类c1继承了c2(公有),c3(私有),c4(保护)
//类c1自身有新数据成员c1_mem,新函数成员fun()
class c1:public c2,private c3,protected c4
{
private:
int c1_mem=0;
public:
int fun();
};

派生类生成过程:

2.2 例7-1 Rectangle类公有继承Point类

/*
7-1 P257
Rectangle类公有继承Point类
派生类Rectangle就包含了它的全部基类中的所有非静态成员(除了构造和析构函数)。
*/
#include <iostream>
using namespace std;
class Point
{
public:
Point(float xx = 0, float yy = 0) : x(xx), y(yy) {}
void initPoint(float x = 0, float y = 0)
{
this->x = x;
this->y = y;
}
void move(float offX, float offY)
{
x += offX;
y += offY;
}
void show() { cout << "this is Point's Show:" << x << y << endl; }
float getX() const { return x; }
float getY() const { return y; } private:
float x, y;
};
class Rectangle : public Point
{
public:
void initRectangle(float x = 0, float y = 0, float w = 0, float h = 0)
{
initPoint(x, y);
this->w = w;
this->h = h;
}
void show() { cout << "this is Rectangle's Show:" << w << h << endl; }
float getW() const { return w; }
float getH() const { return h; } private:
float w, h;
};
int main()
{
Rectangle r1;
r1.initRectangle(1, 1, 3.0, 4.0);
r1.move(2, 1);
cout << r1.getX() << ',' << r1.getY() << ',' << r1.getW() << ',' << r1.getH() << endl;
r1.show();
return 0;
}

2.3 访问控制

2.3.1 总览

基类成员的访问控制

(public)公有继承后

派生类中的访问控制

(private)私有继承后

派生类中的访问控制

(protected)保护继承后

派生类中的访问控制

public public private protected
protected protected private protected
private 不可访问 不可访问 不可访问

详细总览图

基类成员的访问控制

(public)公有继承后

派生类中的访问控制

(private)私有继承后

派生类中的访问控制

(protected)保护继承后

派生类中的访问控制

public

public
在类外通过子类对象访问
可在派生类内访问

private
不可在类外通过子类对象访问
可在派生类内访问
protected
不可在类外通过子类对象访问
可在派生类内访问
protected protected
不可在类外通过子类对象访问
可在派生类内访问
private
不可在类外通过子类对象访问
可在派生类内访问
protected
不可在类外通过子类对象访问
可在派生类内访问
private 不可在派生类内访问
可通过基类成员函数访问
可在基类内访问
不可在派生类内访问
可通过基类成员函数访问
可在基类内访问
不可在派生类内访问
可通过基类成员函数访问
可在基类内访问

写简单测试功能的程序时,可把成员全部写为public(可通过子类对象在类外访问)或者protected(只能在类内访问),全部使用公有继承,这样派生类可访问基类中的所有成员,在类外可通过子类对象访问基类和派生类的所有public成员,程序容易跑。

2.3.2 如何记忆

基类中的成员是private --> 派生类中无法访问此成员

基类中的成员不是private --> 派生类中的访问控制向保守方向发展
从左向右变保守(public->protected->private)
例:基类中成员是protected,继承方式是private,private更保守,故基类成员在派生类中是private

基类的公有成员被公有继承,才可在类外通过子类对象访问基类中的公有成员

2.3.3 public/private/protected

对类A来讲它的成员访问控制如下

成员的访问控制 类外 类内
public 在类外通过A类的对象访问 可被其他成员访问
protected 不可在类外通过A类的对象访问
private 不可在类外通过A类的对象访问

2.4 类型兼容性规则

类型兼容性规则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代

替代之后派生类仅仅发挥出基类的作用(儿子能干爸爸的活,只干爸爸的活)

2.4.1 三个类型兼容性规则

  1. 派生类对象可以隐含转换为基类对象

    //类定义
    class A
    {
    public:
    void display();
    private:
    int x,y;
    };
    class B:public A
    {
    public:
    void display();
    private:
    int i=0,j=0;
    };
    //程序段
    A a1;
    B b1;
    a1 = b1;//派生类对象可以隐含转换为基类对象
  2. 派生类对象可以初始化基类对象的引用
    //类定义
    class A{
    public:
    void display();
    private:
    int x,y;
    };
    class B:public A{
    public:
    void display();
    private:
    int i,j;
    };
    //程序段
    B b1;
    A &rf=b1;//派生类对象可以初始化基类对象的引用
  3. 派生类对象的地址可以隐含转换为指向基类的指针
    //类定义
    class A{
    public:
    void display();
    private:
    int x,y;
    };
    class B:public A{
    public:
    void display();
    private:
    int i,j;
    };
    //程序段
    A *p;
    B b;
    p=&b;//派生类对象的地址可以隐含转换为指向基类的指针

2.4.2 替代之后派生类仅仅发挥出基类的作用

例1:

//类定义
class A{
public:
void display() {cout<<"Class A!";}
private:
int x,y;
};
class B:public A{
public:
void display() {cout<<"Class B!";}
private:
int i,j;
};
//程序段
A *p;
B b;
p=&b;
p->display()
//运行结果
Class A!

例2:

/*
7-3 P264
类型兼容性规则实例
*/
#include <iostream>
using namespace std;
class Base1 //基类Base1定义
{
public:
void display() const
{
cout << "Base1::display()" << endl;
}
};
class Base2 : public Base1 //公有派生类Base2定义
{
public:
void display() const
{
cout << "Base2::display()" << endl;
}
};
class Derived : public Base2 //公有派生类Derived定义
{
public:
void display() const
{
cout << "Derived::display()" << endl;
}
};
void fun(Base1 *p) //参数为执行基类对象的指针
{
//根据类型兼容性规则。派生类对象的地址可以隐含转换为指向基类的指针
p->display();
}
int main()
{
Base1 b1;
Base2 b2;
Derived d1;
fun(&b1);
fun(&b2);
fun(&d1);
return 0;
}

运行结果:

Base1::display()
Base1::display()
Base1::display()

3、派生类的构造函数和析构函数

3.1 派生类构造函数

派生类构造函数语法:

//派生类构造函数格式
派生类名::派生类名(形参表):
基类名1(基类1初始化参数表),…, 基类名n(基类n初始化参数表),
成员对象名1(成员对象名1初始化参数表),… ,成员对象名m(成员对象名m初始化参数表),
基本类型成员初始化列表
{
派生类构造函数的其他初始化操作;
};
//例子,类名Derived
Derived::Derived(int a,int b):
Base1(a),Base2(b),//这里调用基类构造函数
dmem1(a),dmem2(b),//这里调用对象所属类的构造函数
c(a),d(b)//这里是基本数据类型,如int,float,char
{
//其他操作
}
/*
什么时候可不声明派生类的构造函数?
答:需要满足以下条件
1-不需要调用基类中带有参数的构造函数
2-也不需要调用新增加的成员对象的带参数的构造函数
此时全部采用默认构造函数
--当派生类没有显式的构造函数时,系统会隐含生成一个默认构造函数,
该函数会使用基类的默认构造函数对继承自基类的数据初始化,
并且调用类类型的成员对象默认构造函数,对这些成员对象初始化
--注意基本数据类型无默认构造函数
*/

派生类构造函数调用顺序:

3.2 例7-1 派生类构造函数举例

/*
7-4 P266
派生类构造函数举例(多继承,含有内嵌对象)
*/
#include <iostream>
using namespace std;
class Base1
{
public:
Base1(int i) { cout << "Constructing Base1 " << i << endl; }
};
class Base2
{
public:
Base2(int i) { cout << "Constructing Base2 " << i << endl; }
};
class Base3
{
public:
Base3() { cout << "Constructing Base3 *" << endl; }
};
class Derived : public Base2, public Base1, public Base3
{ //基类构造顺序Base2,Base1,Base3
public:
Derived(int a, int b, int c, int d) : Base1(a), m2(d), m1(c), Base2(b) {}
//基类Base1和Base2调用有参数的构造函数,基类Base3调用无参数的构造函数(默认构造函数)
//对象m1和m2调用有参数的构造函数,对象m3调用无参数的构造函数
private:
//对象构造顺序为m1,m2,m3
Base1 m1;
Base2 m2;
Base3 m3;
};
int main()
{
Derived obj(1, 2, 3, 4);
return 0;
}

运行结果:

Constructing Base2 2
Constructing Base1 1
Constructing Base3 *
Constructing Base1 3
Constructing Base2 4
Constructing Base3 *

3.3 派生类复制构造函数(不k)

//派生类复制构造函数格式
Derived::Derived(const Derived &v):Base(v){}
//类型兼容性规则起了作用,可用派生类对象,初始化基类的引用,调用基类的构造函数
//派生类新成员的复制需要自己添加
/*
若没有构造函数,系统会生成一个隐含的构造函数,
这个构造函数会自动调用基类的复制构造函数,
然后对派生类的新成员一一进行复制
*/

delete构造函数

//类定义
class Base
{
public:
Base() = default;
Base(string _info) : info(std::move(_info)) {}
Base(Base &) = delete; //删除复制构造函数
private:
string info;
};
class Derived : public Base{};
//代码段
Derived d1; //正确,合成了默认构造函数
Derived d2(d1); //错误,删除了复制构造函数
//解释
//delete用来禁止默认构造函数或删除复制构造函数阻止拷贝
//基类中删除的构造函数,派生类中也是删除状态。

3.4 派生类析构函数

派生类析构函数的写法没有特别要求

Derived::~Derived(){}//派生类析构函数写法与普通类(无继承关系的类)相同

派生类析构函数会调用基类和对象的析构函数,调用顺序与构造函数的构造顺序严格相反
析构函数执行顺序如下:

3.5 例7-5 派生类析构函数举例(多继承,含有内嵌对象)

/*
7-5 P269
派生类析构函数举例(多继承,含有内嵌对象)
对例7-4进行修改
*/
#include <iostream>
using namespace std;
class Base1
{
public:
Base1(int i) { cout << "Constructing Base1 " << i << endl; }
~Base1() { cout << "Destructing Base1" << endl; };
}; class Base2
{
public:
Base2(int i) { cout << "Constructing Base2 " << i << endl; }
~Base2() { cout << "Destructing Base2" << endl; };
};
class Base3
{
public:
Base3() { cout << "Constructing Base3 *" << endl; }
~Base3() { cout << "Destructing Base3" << endl; };
};
class Derived : public Base2, public Base1, public Base3
{ //基类构造顺序Base2,Base1,Base3
public:
Derived(int a, int b, int c, int d) : Base1(a), m2(d), m1(c), Base2(b) {}
//基类Base1和Base2调用有参数的构造函数,基类Base3调用无参数的构造函数(默认构造函数)
//对象m1和m2调用有参数的构造函数,对象m3调用无参数的构造函数 // Derived类中无析构函数,系统会自动生成默认析构函数
//析构顺序与构造顺序严格相反
private:
//对象构造顺序为m1,m2,m3
Base1 m1;
Base2 m2;
Base3 m3;
};
int main()
{
Derived obj(1, 2, 3, 4);
return 0;
}

运行结果:

Constructing Base2 2
Constructing Base1 1
Constructing Base3 *
Constructing Base1 3
Constructing Base2 4
Constructing Base3 *
Destructing Base3
Destructing Base2
Destructing Base1
Destructing Base3
Destructing Base1
Destructing Base2

4、派生类成员的标识和访问

  1. 作用域分辨符::

    • ::a表示全局作用域的变量a
  2. 如果派生类中声明了与基类成员函数同名的新函数,即使函数的参数表不同,从基类继承的同名函数的所有重载形式也都会被隐藏
    • 不属于函数重载
    • 调用父类同名函数需使用父类名来限制
    • 只有在相同的作用域中定义的函数才可以重载
    • #include <iostream>
      using namespace std;
      class Base{
      public:
      void print(){cout<<"print()"<<endl;}
      void print(int i){cout<<"print(int i)"<<endl;}
      void print(int i, int j){cout<<"print(int i, int j)"<<endl;}
      };
      class Derived:public Base{
      public:
      void print(int i, int j, int k){cout<<"print(int i, int j, int k)"<<endl;}
      };
      int main() {
      Derived d;
      d.print(); //错误,基类中所有print()的重载形式都被隐藏了
      d.print(1); //错误,基类中所有print()的重载形式都被隐藏了
      d.print(2,3); //错误,基类中所有print()的重载形式都被隐藏了
      d.print(1,2,3);//正确
      return 0;
      }
  3. 如果某派生类的多个基类拥有同名的成员,同时,派生类又新增这样的同名成员,则派生类成员将隐藏所有基类的同名成员
    • 如要通过派生类对象访问基类中被覆盖的同名成员,应使用基类名限定

      类名::成员名        //访问数据成员
      类名::成员名(参数表) //访问函数成员
    • 例7-6 多继承同名隐藏规则
      /*
      7-6 P273
      多继承同名隐藏规则
      */
      #include <iostream>
      using namespace std;
      class Base1 //定义基类Base1
      {
      public:
      int var;
      void fun() { cout << "Member of Base1:" << var << endl; }
      };
      class Base2 //定义基类Base2
      {
      public:
      int var;
      void fun() { cout << "Member of Base2:" << var << endl; }
      };
      class Derived : public Base1, public Base2 //定义派生类Derived
      {
      public:
      int var;
      void fun() { cout << "Member of Derived:" << var << endl; }
      }; int main()
      {
      Derived d;
      Derived *p = &d; d.var = 1; //访问Derived类成员
      d.fun(); d.Base1::var = 2; //访问Base1类成员
      d.Base1::fun(); p->Base2::var = 3; //访问Base2类成员
      p->Base2::fun();
      return 0;
      }
      运行结果:

      Member of Derived:1
      Member of Base1:2
      Member of Base2:3
  4. 如果从不同基类继承了同名成员,但是在派生类中没有定义同名成员,则访问成员存在二义性问题(因为基类里的同名函数没有被覆盖,用派生类对象或指针访问该同名函数时,不知道哪一个)
    • 如下程序有二义性

      //类定义
      class A {
      public:
      void f();//二义性
      };
      class B {
      public:
      void f();//二义性
      void g();//被类C中的g()覆盖
      };
      class C: public A, public B {
      public:
      void g();//覆盖了类B中的g()
      };
      //程序段
      C c1;
      c1.f(); //有二义性
      c1.g(); //无二义性
    • 解决1:用类名限定
      //程序段
      C c1;
      c1.A::f();//无二义性
      c1.B::f();//无二义性
    • 解决2:同名隐藏
      //类定义
      class A {
      public:
      void f();//无二义性
      };
      class B {
      public:
      void f();//无二义性
      void g();//被类C中的g()覆盖
      };
      class C: public A, public B {
      public:
      void g();//覆盖了类B中的g()
      void f()//在C 中声明一个同名成员函数f(),f()再根据需要调用
      {
      if(1/*需要调用A中的fun*/)
      A::f();
      else/*需要调用B中的fun*/
      B::f();
      }
      };
      //程序段
      C c1;
      c1.f();//调用C中的f()
  5. 如果某个派生类的部分或全部直接基类是从另一个共同的基类派生而来,在这些直接基类中,从上一级基类继承来的成员就拥有相同的名称,因此派生类中也就会产生同名现象,对这种类型的同名成员也要使用作用域分辨符来唯一标识,而且必须用直接基类来限定
    • 解决:
    • 虽然可以通过类名限定来解决这个问题,但是会造成冗余不一致的问题
      • 冗余:表达相同含义的变量有两个,多余了
      • 不一致性:表达相同含义的变量有两个,通过作用域分辨符可以分开赋值,操作上没问题,但是这样就导致相同含义的变量被赋予了不同的值,表意不一致
      • 下面会讲虚基类,可解决以上两个问题

5、虚基类

  1. 解决的问题:

    • 消除类继承过程中产生的冗余不一致性
  2. 虚基类声明方式
    • class B1:virtual public B
      {}
  3. 注意
    • 第一级继承时就要将共同基类设计为虚基类
  4. 刚才的问题被解决了!
    • 例7-8 虚基类举例

      /*
      7-8 P77
      虚基类举例
      */
      #include <iostream>
      using namespace std;
      class Base0 //定义基类Base0
      {
      // Base0是最远虚基类
      //虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。
      //在建立对象时,只有最远派生类的构造函数调用虚基类的构造函数,其他类对虚基类构造函数的调用被忽略。
      public:
      int var0;
      void fun0() { cout << "Base0 var0=" << var0 << endl; }
      };
      class Base1 : virtual public Base0 //定义派生类Base1
      {
      public: //新增外部接口
      int var1;
      };
      class Base2 : virtual public Base0 //定义派生类Base2
      {
      public: //新增外部接口
      int var2;
      };
      class Derived : public Base1, public Base2 //定义派生类Derived
      { // Derived是最远派生类
      public: //新增外部接口
      int var;
      void fun() { cout << "Derived" << endl; }
      };
      int main()
      {
      Derived d;
      d.var0 = 2; //直接访问虚基类的数据成员
      d.fun0(); //直接访问虚基类的函数成员
      return 0;
      }


  5. 虚基类的注意事项
    • 虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。

      • 若不需要使用虚基类的带参构造函数,可以让系统默认生成
      • 如果,虚基类声明有非默认形式(带参数的)的构造函数,并且没有声明默认构造函数,那么,在整个继承关系中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化列表中列出对虚基类的初始化。
      • 在建立对象时,只有最远派生类的构造函数调用虚基类的构造函数其他类对虚基类构造函数的调用被忽略
      • 查看代码
        #include <iostream>
        using namespace std;
        class Base0
        {
        public:
        Base0(int var) : var0(var) {}
        int var0;
        void fun0() { cout << "Member of Base0" << endl; }
        };
        class Base1 : virtual public Base0
        {
        public:
        //构造函数中对虚基类初始化(只有最远派生类中的初始化会执行)
        Base1(int var) : Base0(var) {}
        int var1;
        };
        class Base2 : virtual public Base0
        {
        public:
        //构造函数中对虚基类初始化(只有最远派生类中的初始化会执行)
        Base2(int var) : Base0(var) {}
        int var2;
        };
        class Derived : public Base1, public Base2
        {
        public:
        //构造函数中对虚基类初始化(只有最远派生类中的初始化会执行,就是这儿!)
        Derived(int var) : Base0(var), Base1(var), Base2(var)
        {
        }
        int var;
        void fun()
        {
        cout << "Member of Derived" << endl;
        }
        };
        int main()
        { //程序主函数
        Derived d(1);
        d.var0 = 2; //直接访问虚基类的数据成员
        d.fun0(); //直接访问虚基类的函数成员
        return 0;
        }
    • 派生类类构造函数的执行顺序

参考:

C++语言程序设计(第5版),郑莉,清华大学

【C++复习】第七章 类的继承(基类、派生类、虚基类)的更多相关文章

  1. 《数据结构与算法分析:C语言描述》复习——第七章“哈希”——哈希表

    2014.06.22 12:36 简介: 哈希是一种数学思想,将不定长数据通过函数转换为定长数据.不定长数据通常意味着碎片化,动态分配内存等等影响存储和性能的因素.当这个定长数据是一个无符号整数时,可 ...

  2. C#图解第七章:类和继承

    1.类继承 通过继承我们可以定义一个新类,新类纳入一个已经声明的类并进行扩展. 1.可以使用- 一个已经存在的类作为新类的基础..已存在的类称为基类(baseclass),新类称为派生类(derive ...

  3. C#图解:第七章

    C#图解第七章:类和继承 1.类继承 通过继承我们可以定义一个新类,新类纳入一个已经声明的类并进行扩展. 1.可以使用- 一个已经存在的类作为新类的基础..已存在的类称为基类(baseclass),新 ...

  4. JVM学习笔记-第七章-虚拟机类加载机制

    JVM学习笔记-第七章-虚拟机类加载机制 7.1 概述 Java虚拟机描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被 ...

  5. 精读JavaScript模式(八),JS类式继承

    一.前言 这篇开始主要介绍代码复用模式(原书中的第六章),任何一位有理想的开发者都不愿意将同样的逻辑代码重写多次,复用也是提升自己开发能力中重要的一环,所以本篇也将从“继承”开始,聊聊开发中的各种代码 ...

  6. 《深入理解java虚拟机》 第七章虚拟机类加载机制

    第七章 虚拟机类加载机制   7.1概述 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行检验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型,这就是虚拟机的类加载机制. 在 ...

  7. java 第七章 面向对象高级特性

    一.类的继承 (一)继承的含义 1.在Java中定义一个类时,让该类通过关键字extends继承一个已有的类,这就是类的继承(泛化). 2.被继承的类称为父类(超类,基类),新的类称为子类(派生类). ...

  8. 【C++】继承(虚基类)

    类的继承与派生 面向对象技术强调软件的可重用性,这种重用性通过继承机制来实现.而在类的继承过程中,被重用的原有类称为基类,新创建的类称为派生类.派生类定义语法格式如下: class <派生类名& ...

  9. python3 入门 (四) 类与继承

    Python 类 Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法. 对象可以包含任意数量和类型的数据. p ...

  10. 继承虚函数浅谈 c++ 类,继承类,有虚函数的类,虚拟继承的类的内存布局,使用vs2010打印布局结果。

    本文笔者在青岛逛街的时候突然想到的...最近就有想写几篇关于继承虚函数的笔记,所以回家到之后就奋笔疾书的写出来发布了 应用sizeof函数求类巨细这个问题在很多面试,口试题中很轻易考,而涉及到类的时候 ...

随机推荐

  1. Centos7 安装mysql 5.7 教程

    安装 yum 源 需要在系统上启用 MySQL 5.7 Community Release YUM 存储库.用于 yum 存储库配置的 rpm 包可在 MySQL 的官方网站上找到. 首先将最新的My ...

  2. Docker之Elastic Search&Kibana保姆级别安装

    Docker之Elastic Search&Kibana保姆级别安装: 如果觉得样式不好:跳转即可 http://www.lifengying.site/(md文件复制过来有些样式会不一样) ...

  3. C++ 手动实现栈(stack) (课后作业版)

    栈,一种遵循先进先出原则的数据结构,可以用顺序表实现,也可以用链表进行实现. 这里我使用数组实现方法,包含了进栈,出栈,访问栈顶等功能,以及一些辅助功能. 栈Stack类定义如下: template ...

  4. pychars的使用

    1|0安装 pyecharts 兼容 Python2 和 Python3.目前版本为 0.1.2 pip install pyecharts 2|0入门 首先开始来绘制你的第一个图表 from pye ...

  5. flask-基础篇03 请求钩子与上下文

    一.异常处理 1.HTTP 异常主动抛出 ①abort 方法: 抛出一个给定状态代码的 HTTPException 或者 指定响应,例如想要用一个页面未找到页面未找到异常来终止请求,你可以调用 abo ...

  6. kubernetes构架及组件介绍

    传统部署时代 早期在物理机上直接运行应用程序,无法对其定义资源边界,导致资源不分配,其他的程序性能下降 虚拟化部署时代 虚拟化允许应用程序在VM之间隔离,并提供安全界别,但是不能自由访问应用程序 因为 ...

  7. HIVE- INSERT 方法使用

    (1) INSERT INTOINSERT INTO tableVALUES ('aaa' , 111),('bbb' , 222); (2) insert overwrite insert over ...

  8. 利用拉格朗日乘子法从最优化问题中推导出KKT条件

    优化问题的一般形式 在优化问题中,我们将其一般形式定义为有约束(不等式约束.等式约束)的最小化优化问题,其具体定义如下: \[\begin{array}{ll} \min _{x} & f_{ ...

  9. win10开机无限自动修复篇

    转载请注明来源:https://www.cnblogs.com/Sherlock-L/p/15521381.html 关键词:win10.开机无限自动修复.nvlddmkm.sys 哈哈哈,其实这篇随 ...

  10. lua module以及模块内的local function使用

    在模块定义local function,使用local function时,需要在使用前就定义,不能通过self:localfunction 或者self.locakfunction 因为是模块内的局 ...