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. 2.3 在DispatcherServlet的构造方法中解析applicationContext.xml配置文件

    package com.hy.servlet; import java.io.IOException; import java.io.InputStream; import java.util.Map ...

  2. javaweb同一个项目打包两次放在同一个tomcat下

    web.xml中配置: <context-param> <param-name>webAppRootKey</param-name> <param-value ...

  3. java链接pg数据库remaining connection slots are reserved for non-replication superuser connections问题

    最近遇到链接pg数据库报错:remaining connection slots are reserved for non-replication superuser connections.百度说, ...

  4. vue element 日期范围选择器限制:只能选今天之前的时间 || 只能选今天之后的时间 || 选取今天往后三天内

    举例:只能选今天或者今天之后的时间(如下图) <el-date-picker clearable v-model="form.limitTime" type="da ...

  5. Tech&W_STU_Resource_bookmark

    整合资料 1 architecture: Enterprise integration patterns : https://www.enterpriseintegrationpatterns.com ...

  6. linux挂载磁盘步骤

    一.查看需要挂载设备,如下sda(默认路径/dev/sda) 二.新建分区,执行如下命令进入操作 fdisk /dev/sda 1.m 查看可操作的命令 2.键入 n ,根据需要新建分区 3.键入 d ...

  7. Chrome禁用开发者工具

    在一次工作中,所做的项目要求页面中不能右击,不能打开F12.一般来说可以禁用F12的按键,但是可以通过开发者工具进入.经过个人实验,以下方法适用于谷歌浏览器.火狐浏览器,以及使用谷歌内核的浏览器(如Q ...

  8. snapshot备份

    snapshot C: "h:\esd\$date_$hour_$minute_C.sna" -L0 -R -G snapshot64.exe C: "H:\ESD\$d ...

  9. 配置VS Code链接外部gsl库文件

    配置VS code在C语言中调用gsl库文件 gsl安装 sudo apt-get install libgsl0-dev 先确认gsl库,gcc都已正确安装,命令行 gcc -L/usr/local ...

  10. MOBI 】逆流而上的我:重塑心理韧性,在逆境中实现自我超越【早稻田大学名誉教授、哈佛大学客座研究

    书本详情 标题:逆流而上的我:重塑心理韧性,在逆境中实现自我超越[早稻田大学名誉教授.哈佛大学客座研究员加藤谛三的年度心理学温情巨作!掌握心理韧性,每个人都是生活的修行者!] | 加藤谛三 |年份:2 ...