我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++中的多态如何实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++中的多态如何实现

这篇文章主要介绍“C++中的多态如何实现”,在日常操作中,相信很多人在C++中的多态如何实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++中的多态如何实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

    多态概念引入

    多态字面意思就是多种形态。

    我们先来想一想在日常生活中的多态例子:买票时,成人买票全价,如果是学生那么半价,如果是军人,就可以优先买票。不同的人买票会有不同的实现方法,这就是多态。

    1、C++中多态的实现

    1.1 多态的构成条件

    C++的多态必须满足两个条件:

    1 必须通过基类的指针或者引用调用虚函数

    2 被调用的函数是虚函数,且必须完成对基类虚函数的重写

    我们来看看具体实现。

    class Person //成人{  public:  virtual void fun()   {       cout << "全价票" << endl; //成人票全价   }};class Student : public Person //学生{   public:   virtual void fun() //子类完成对父类虚函数的重写   {       cout << "半价票" << endl;//学生票半价   }};void BuyTicket(Person* p){   p->fun();}int main(){   Student st;   Person p;   BuyTicket(&st);//子类对象切片过去   BuyTicket(&p);//父类对象传地址}

    调用的两个BuyTicket() 答案是什么呢?

    C++中的多态如何实现

    如果不满足多态呢?

    C++中的多态如何实现

    这说明了很重要的一点,如果满足多态,编译器会调用指针指向对象的虚函数,而与指针的类型无关。如果不满足多态,编译器会直接根据指针的类型去调用虚函数。

    1.2 虚函数

    用virtual修饰的关键字就是虚函数。

    虚函数只能是类中非静态的成员函数。

    virtual void fun() //error! 在类外面的函数不能是虚函数{}

    1.3虚函数的重写

    子类和父类中的虚函数拥有相同的名字,返回值,参数列表,那么称子类中的虚函数重写了父类的虚函数,或者叫做覆盖。

    class Person{  public:   virtual void fun()   {      cout << "Person->fun()" << endl;   }};class Student{   public:   //子类重写的虚函数可以不加virtual,因为子类继承了父类的虚函数,   //编译器会认为你是想要重写虚函数。   //void fun() 可以直接这样,也对,但不推荐。              virtual void fun()//子类重写父类虚函数   {     cout << "Student->fun()" << endl;   }};

    虚函数重写的两个例外:

    协变:

    子类的虚函数和父类的虚函数的返回值可以不同,也能构成重载。但需要子类的返回值是一个子类的指针或者引用,父类的返回值是一个父类的指针或者引用,且返回值代表的两个类也成继承关系。这个叫做协变。

    class Person{  public:   virtual Person* fun()//返回父类指针   {      cout << "Person->fun()" << endl;      return nullptr;   }};class Student{   public:            //返回子类指针,虽然返回值不同,也构成重写   virtual Student* fun()//子类重写父类虚函数   {     cout << "Student->fun()" << endl;     return nullptr;   }};

    也可以这样,也是协变,

    class A{};class B : public A{};   //B继承Aclass Person{  public:   virtual A* fun()//返回A类指针   {      return nullptr;   }};class Student{   public:            //返回B类指针,虽然返回值不同,也构成重写   virtual B* fun()//子类重写父类虚函数   {     return nullptr;   }};

    析构函数的重写

    析构函数是否需要重写呢?

    让我们来考虑这样一种情况,

    //B继承了A,他们的析构函数没有重写。class A{  public:  ~A()  {     cout << "~A()" << endl;  }};class B : public A{  public:  ~B()  {    cout << "~B()" << endl;  }}; A* a = new B; //把B的对象切片给A类型的指针。 delete a; //调用的是谁的析构函数呢?你希望调用谁的呢?

    显然我们希望调用B的析构函数,因为我们希望析构函数的调用跟指针指向的对象有关,而跟指针的类型无关。这不就是多态吗?但是结果却调用了A的析构函数。

    所以析构函数要实现多态。But,析构函数名字天生不一样,怎么实现多态?

    实际上,析构函数被编译器全部换成了Destructor,所以我们加上virtual就可以。

    只要父类的析构函数用virtual修饰,无论子类是否有virtual,都构成析构。

    这也解释了为什么子类不写virtual可以构成重写,因为编译器怕你忘记析构。

    class A{  public: virtual  ~A()  {     cout << "~A()" << endl;  }};class B : public A{  public:  virtual ~B()  {    cout << "~B()" << endl;  }};

    1.4 C++11 override && final

    C++11新增了两个关键字。用final修饰的虚函数无法重写。用final修饰的类无法被继承。final像这个单词的意思一样,这就是最终的版本,不用再更新了。

    class A final //A类无法被继承{public:  virtual void fun() final //fun函数无法被重写  {}};class B : public A //error{  public:    virtual void fun() //error    {     cout << endl;    }};

    被override修饰的虚函数,编译器会检查这个虚函数是否重写。如果没有重写,编译器会报错。

    class A  {public:  virtual void fun()   {}};class B : public A {  public:  //这里我想重写fun,但写成了fun1,因为有override,编译器会报错。    virtual void fun1() override    {     cout << endl;    }};

    1.5 重载,覆盖(重写),重定义(隐藏)

    这里我们来理一理这三个概念。

    重载:重载函数处在同一作用域。

    函数名相同,函数列表必须不同。

    覆盖:必须是虚函数,且处在父类和子类中。

    返回值,参数列表,函数名必须完全相同(协变除外)。

    重定义:子类和父类的成员变量相同或者函数名相同,

    子类隐藏父类的对应成员。

    子类和父类的同名函数不是重定义就是重写。

    2、抽象类

    2.1 抽象类的概念

    再虚函数的后面加上=0就是纯虚函数,有纯虚函数的类就是抽象类,也叫做接口类。抽象类无法实例化出对象。抽象类的子类也无法实例化出对象,除非重写父类的虚函数。

    class Car{ public:    virtual void fun() = 0; //不用实现,只写接口就行。}

    这并不意味着纯虚函数不能写实现,只是我们大部分情况下不写。

    那么虚函数有什么用呢?

    1,强制子类重写虚函数,完成多态。

    2,表示某些抽象类。

    2.2 接口继承和实现继承

    普通函数的继承就是实现继承,虚函数的继承就是接口继承。子类继承了函数的实现,可以直接使用。虚函数重写后只会继承接口,重写实现。所以如果不用多态,不要把函数写成虚函数。

    纯虚函数就体现了接口继承。下面我们来一道题,展现一下接口继承。

    class A{   public:   virtual void fun(int val = 0)//父类虚函数   {     cout <<"A->val = "<< val << endl;   }   void Fun()   {      fun();//传过来一个子类指针调用fun()   }};class B: public A{   public:    virtual void fun(int val = 1)//子类虚函数    {       cout << "B->val = " << val << endl;    }};B b;A* a = &b;a->Fun();

    结果是什么呢?

    B->val = 0

    子类对象切片给父类指针,传给Fun函数,满足多态,会去调用子类的fun函数,但是子类的虚函数继承了父类的接口,所以val是父类的0.

    3、 多态的原理

    3.1 虚函数表

    多态是怎样实现的呢?

    先来一道题目,

    class A{  public:   virtual void fun()   {}   protected:   int _a;};

    sizeof(A)是多少?是4吗?NO,NO,NO!

    答案是8个字节。

    我们定义一个A类型的对象a,打开调试窗口,发现a的内容如下

    C++中的多态如何实现

    我们发现除了成员变量_a以外,还多了一个指针。这个指针是不准确的,实际上应该是_vftptr(virtual function table pointer),即虚函数表指针,简称虚表指针。在计算类大小的时候要加上这个指针的大小。那么虚表是什么呢?虚表就是存放虚函数的地址地方。每当我们去调用虚函数,编译器就会通过虚表指针去虚表里面查找。

    下面我们用一个小栗子来说明虚函数的使用会用指针。

    class A{  public:  void fun1()  {}  virtual void fun2()  {}};A* ap = nullptr;ap->fun1(); //调用成功,因为这是普通函数的调用ap->fun2(); //调用失败,虚函数需要对指针操作,无法操作空指针。

    我们先来看看继承的虚函数表。

    class A{  public:   virtual void fun1()   {}   virtual void fun2()   {}};class B : public A{ public:   virtual void fun1()//重写父类虚函数   {}   virtual void fun3()   {}};A a;B b; //我们通过调试看看对象a和b的内存模型。

    C++中的多态如何实现

    子类跟父类一样有一个虚表指针。

    子类的虚函数表一部分继承自父类。如果重写了虚函数,那么子类的虚函数会在虚表上覆盖父类的虚函数。

    本质上虚函数表是一个虚函数指针数组,最后一个元素是nullptr,代表虚表的结束。

    所以,如果继承了虚函数,那么

    1 子类先拷贝一份父类虚表,然后用一个虚表指针指向这个虚表。

    2 如果有虚函数重写,那么在子类的虚表上用子类的虚函数覆盖。

    3 子类新增的虚函数按其在子类中的声明次序增加到子类虚表的最后。

    C++中的多态如何实现

    下面来一道面试题:

    虚函数存在哪里?

    虚函数表存在哪里?

    虚函数是带有virtual的函数,虚函数表是存放虚函数地址的指针数组,虚函数表指针指向这个数组。对象中存的是虚函数指针,不是虚函数表。

    虚函数和普通函数一样存在代码段。

    那么虚函数表存在哪里呢?

    我们创建两个A对象,发现他们的虚函数指针相同,这说明他们的虚函数表属于类,不属于对象。所以虚函数表应该存在共有区。

    堆?堆需要动态开辟,动态销毁,不合适。

    静态区?静态区存放全局变量和静态变量不合适。

    所以综合考虑,把虚函数表也存放在了代码段。

    3.2多态的原理

    我们现在来看看多态的原理。

    class Person //成人{  public:  virtual void fun()   {       cout << "全价票" << endl; //成人票全价   }};class Student : public Person //学生{   public:   virtual void fun() //子类完成对父类虚函数的重写   {       cout << "半价票" << endl;//学生票半价   }};void BuyTicket(Person* p){   p->fun();}

    C++中的多态如何实现

    这样就实现了不同对象去调用同一函数,展现出不同的形态。

    满足多态的函数调用是程序运行是去对象的虚表查找的,而虚表是在编译时确定的。

    普通函数的调用是编译时就确定的。

    3.3动态绑定与静态绑定

    静态绑定又称为前期绑定(早绑定),在程序编译期间确定了程序的行为,也称为静态多态,比如:函数重载

    动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体行为,调用具体的函数,也称为动态多态。

    我们说的多态一般是指动态多态。

    这里我附上一个有意思的问题:

    就是在子类已经覆盖了父类的虚函数的情况下,为什么子类还是可以调用“被覆盖”的父类的虚函数呢?

    #include <iostream>using namespace std;class Base {public:virtual void func() {cout << "Base func\n";}};class Son : public Base {public:void func() {Base::func();cout << "Son func\n";}};int main(){Son b;b.func();return 0;}

    输出:Base func

    Son func

    这是C++提供的一个回避虚函数的机制

    通过加作用域(正如你所尝试的),使得函数在编译时就绑定。

    (这题来自:虚函数)

    4 、继承中的虚函数表

    4.1 单继承中的虚函数表

    这里DV继承BV。

    class BV{public:virtual void Fun1(){cout << "BV->Fun1()" << endl;}virtual void Fun2(){cout << "BV->Fun2()" << endl;}};class DV : public BV{public:virtual void Fun1(){cout << "DV->Fun1()" << endl;}virtual void Fun3(){cout << "DV->Fun3()" << endl;}virtual void Fun4(){cout << "DV->Fun4()" << endl;}};

    我们想个办法打印虚表,

    typedef void(*V_PTR)(); //typedef一下函数指针,相当于把返回值为void型的//函数指针定义成 V_PTR.void PrintPFTable(V_PTR* table)//打印虚函数表{  //因为虚表最后一个为nllptr,我们可以利用这个打印虚表。for (size_t i = 0; table[i] != nullptr; ++i){printf("table[%d] : %p->", i, table[i]);V_PTR f = table[i];f();cout << endl;}}BV b;DV d;      // 取出b、d对象的前四个字节,就是虚表的指针,      //前面我们说了虚函数表本质是一个存虚函数指针的指针数组,      //这个数组最后面放了一个nullptr     // 1.先取b的地址,强转成一个int*的指针     // 2.再解引用取值,就取到了b对象前4个字节的值,这个值就是指向虚表的指针     // 3.再强转成V_PTR*,这是我们打印虚表函数的类型。     // 4.虚表指针传给PrintPFTable函数,打印虚表     // 5,有时候编译器资源释放不完全,我们需要清理一下,不然会打印多余结果。PrintPFTable((V_PTR*)(*(int*)&b));PrintPFTable((V_PTR*)(*(int*)&d));

    结果如下:

    C++中的多态如何实现

    4.2 多继承中的虚函数表

    我们先来看一看一道题目,

    class A{public: virtual void fun1() {   cout << "A->fun1()" << endl; } protected: int _a;};class B{public: virtual void fun1() {   cout << "B->fun1()" << endl; }  protected:  int _b;};class C : public A, public B{  public:  virtual void fun1()  {    cout << "C->fun1()" << endl;  }  protected:  int _c;};C c;//sizeof(c) 是多少呢?

    sizeof( c )的大小是多少呢?是16吗?一个虚表指针,三个lnt,考虑内存对齐后确实是16.但是结果是20.

    我们来看看内存模型。在VS下,c竟然有两个虚指针

    C++中的多态如何实现

    每个虚表里都有一个fun1函数。

    所以C的内存模型应该是这样的,

    C++中的多态如何实现

    而且如果C自己有多余的虚函数,会按照继承顺序补在第一张虚表后面。

    下面还有一个问题,可以看到C::fun1在两张虚表上都覆盖了,但是它们的地址不一样,是不是说在代码段有两段相同的C::fun1呢?

    不是的。实际上两个fun1是同一个fun1,里面放的是跳转指令而已。C++也会不犯这个小问题。

    最后,我们来打印一下多继承的虚表。

    //Derive继承Base1和Base2class Base1{public:virtual void fun1(){cout << "Base1->fun1()" << endl;}virtual void fun2(){cout << "Base1->fun2()" << endl;}};class Base2{public:virtual void fun1(){cout << "Base2->fun1()" << endl;}virtual void fun2(){cout << "Base2->fun2()" << endl;}};class Derive : public Base1, public Base2{public:virtual void fun1(){cout << "Derive->fun1()" << endl;}virtual void fun3(){cout << "Derive->fun3()" << endl;}};

    打印的细节,从Base2继承过来的虚表指针放在第一个虚表指针后面,我们想要拿到这个指针需要往后挪一个指针加上一个int的字节,但是指针的大小跟操作系统的位数有关,所以我们可以用加上Base2的大小个字节来偏移。

    这里注意要先强转成char*,不然指针的加减会根据指针的类型来确定。

    Derive d;PrintPFTable((V_PTR*)(*(int*)&d));PrintPFTable((V_PTR*)(*(int*)((char*)&d+sizeof(Base2))));

    Ret:

    C++中的多态如何实现

    到此,关于“C++中的多态如何实现”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    C++中的多态如何实现

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    C++中的多态如何实现

    这篇文章主要介绍“C++中的多态如何实现”,在日常操作中,相信很多人在C++中的多态如何实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++中的多态如何实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧
    2023-06-30

    C#多态如何实现

    小编给大家分享一下C#多态如何实现,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!C#实现多态主要有3种方法,虚方法,抽象类,接口1 虚方法在父类的方法前面加关键字
    2023-06-14

    c++多态如何实现

    多态是面向对象编程中允许对象具有不同形式或行为的一种机制。c++ 中的多态通过虚函数、抽象类、纯虚函数和动态绑定实现。虚函数允许派生类重新定义基类方法,抽象类包含必须在派生类中重新定义的虚函数,纯虚函数没有任何实现,只存在于抽象类中,而动态
    c++多态如何实现
    2024-04-22

    如何实现C#继承与C#多态

    这篇文章主要讲解了“如何实现C#继承与C#多态”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何实现C#继承与C#多态”吧!在C#中实现OOP思想,丝毫不逊色于Java,下面我通知两句话来帮
    2023-06-17

    java中的多态如何实现

    在Java中实现多态的方式是通过方法的重写和方法的重载。多态是指相同的方法名在不同的类中具有不同的实现,使得可以通过父类引用指向子类对象,调用子类中重写的方法。具体来说,实现多态的步骤如下:创建一个父类和多个子类,父类中定义一个方法。在
    java中的多态如何实现
    2024-03-14

    如何理解C++多态的实现过程

    如何理解C++多态的实现过程,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。多态描述的是使用基类的指针或引用操作多个类型的能力。我们知道,子类的指针是可以隐式转化为父类的,所
    2023-06-17

    C++中怎么实现多态

    C++中怎么实现多态,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。实现了C++多态 2 5 1 6#include < iostream> using namespace st
    2023-06-17

    java中的多态是如何实现的

    什么是多态面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。多态的定义指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)实现多态的技术动态绑定(dyna
    java中的多态是如何实现的
    2017-08-04

    如何在Java中实现多态

    小编给大家分享一下如何在Java中实现多态,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!/**题目: 人可以(孩子,学生,老师) 吃 水果(苹果,葡萄,芒果,菠萝)思路:1. 抽象出类 : 人(Person){孩子(Bab
    2023-06-02

    Golang中如何实现多态性?

    Golang中的多态性如何发挥作用?在Golang中,多态性是通过接口实现的。通过接口可以实现多个不同类型的对象统一使用的能力,这使得我们可以更灵活地编写代码和处理不同类别对象的逻辑。接下来,本文将介绍Golang中多态性的概念和如何使用接
    Golang中如何实现多态性?
    2023-12-29

    PHP中如何实现多态性?

    php 中的多态性允许不同对象共享相同接口,同时拥有独特的行为。通过接口和抽象类实现:接口定义方法签名,而不提供实现。对象必须实现接口中的所有方法。抽象类包含未实现的方法,只能在子类中实现。实战示例:定义动物行为接口 animalactio
    PHP中如何实现多态性?
    2024-05-21

    如何在php中实现多态

    本篇文章给大家分享的是有关如何在php中实现多态,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对
    2023-06-15

    C#中怎么实现多态性

    在C#中实现多态性一般通过继承和接口实现。具体方法如下:继承:通过创建一个父类和多个子类,子类继承父类的特性,并且可以重写父类的方法来实现多态性。例如:class Animal{public virtual void MakeSound(
    C#中怎么实现多态性
    2024-03-06

    C++ 函数重载如何实现多态性?

    函数重载可用于实现多态性,即通过基类指针调用派生类方法,编译器根据实际参数类型选择重载版本。示例中,animal 类定义虚拟 makesound() 函数,dog 和 cat 类重写该函数,通过 animal* 指针调用 makesound
    C++ 函数重载如何实现多态性?
    2024-04-13

    java如何实现多态

    Java多态概述:(推荐:java视频教程)多态是面向对象编程语言的重要特性,它允许基类的指针或引用指向派生类的对象,而在具体访问时实现方法的动态绑定。Java 对于方法调用动态绑定的实现主要依赖于方法表,但通过类引用调用(invokevitual)和接口引用
    java如何实现多态
    2020-07-13

    golang如何实现多态

    go 中没有传统多态,但可以利用接口和反射实现类似效果:定义接口,明确方法集。创建多个类型,实现该接口。使用反射,动态调用方法,无需了解具体类型。Go 中实现多态如何实现?Go 中没有传统意义上的多态,但可以使用接口和反射机制来实现类似
    golang如何实现多态
    2024-04-21

    java多态是如何实现的

    在面向对象编程(Object-Oriented Programming, OOP)中,多态机制无疑是其最具特色的功能,甚至可以说,不运用多态的编程不能称之为OOP。本质上多态分两种:编译时多态(又称静态多态),运行时多态(又称动态多态)
    java多态是如何实现的
    2020-01-11

    java是如何实现多态的

    多态就是指一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。 (推荐学习:java课程)因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量
    java是如何实现多态的
    2020-04-17

    C#中如何实现多线程

    在C#中实现多线程可以使用Thread类或Task类。以下是两种常用的实现方式:使用Thread类:using System;using System.Threading;class Program{static void Main()
    C#中如何实现多线程
    2024-04-03

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录