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. replace 常用积累

    1.替换有,或者.为: obj.keyword.replace(/,|./g,';') 2.替换元素标签类似于<em>文字</em>这种 let name=item.name. ...

  2. TensorFlow的基础结构

    Tensorflow 是非常重视结构的, 我们得建立好了神经网络的结构, 才能将数字放进去, 运行这个结构. 这个例子简单的阐述了 tensorflow 当中如何用代码来运行我们搭建的结构. 创建数据 ...

  3. oralce 语句指定的转换无效

    公司的小师妹出现了个问题   让我帮忙看一下 在plsql 中查询语句没问题, 但是放到程序中会提示指定的转换无效  是因为存在无限小数  加上round(JJYHL,2) JJYHL就可以了

  4. mac + win ,用python一行代码批量下载哔哩哔哩视频

    ​ 首先,你的机器已经安装python,然后是安装you-get. 打开终端,输入 pip3 install you-get,回车,即开始安装,如下图所示. ​编辑 安装成功后,比如要下载某个视屏,首 ...

  5. element-ui组件Table排序(sort-by),某些数据无需排序

    在列中设置 sortable 属性即可实现以该列为基准的排序, 接受一个 Boolean,默认为 false. 可以通过 Table 的 default-sort 属性设置默认的排序列和排序顺序. 可 ...

  6. Mysql压缩包版本安装

    之前一直使用的是安装包,今天懒得去下载了,直接用压缩包安装,记录一下. 1.先去官网下载压缩包.https://dev.mysql.com/downloads/mysql/8.0.html 2.将文件 ...

  7. 18.SQLite应用案例-课程表

    一.程序界面 1.课程表首页 一周有7天,一天有10节课. 课程表首页的布局activity_main.xml框架设计大致如此: 最外层使用线性布局设置屏幕水平方向android:orientatio ...

  8. Cgroup学习笔记3—代码实现—相关结构和全局变量

    基于 LInux-5.10 一.相关结构 1. 通过多次的 #define 和 #undef SUBSYS 宏来展开 cgroup_subsys.h 中通过 deconfig 使能的 cgroup 子 ...

  9. 【笔记】Win7连接公司内网无法打开网页

    win7尝试使用VPN连接公司内网发现无法打开单点登录网页 DNS解析没问题 服务器也能ping通 查了半天才发现是MTU的问题 win7的默认值1400 公司的华为设备设置的比这个值小 要根据具体的 ...

  10. 没有可用软件包 iostat。

    说明: iostat 主要用于监控系统设备的IO负载情况,根据这个可以看出当前系统的写入量和读取量,CPU负载和磁盘负载. iostat 命令的输出结果包含了很多信息,以下是一些常见的统计指标的解释: ...