C++_16_继承和派生


C++继承和派生

继承和派生的概念:

  继承和派生 是 “类” 和 “类” 之间的关系,描述的是从一个类到另一个类的过程,继承和派生是描述的同一个过程,只不过看待的角度不同
  先出现的类是父类或基类,后生成的类是子类

    
继承:子类父类叫做继承
    派生:父类子类叫做派生
  由于派生类可以将基类的代码继承过来,无需重新设计,因而继承解决了代码重用的问题,大大提高了软件的开发效率。同时如果这些代码在基类中运行无误,则继承之后到派生类中运行也是不会有问题的。
  派生和继承可以叠加嵌套,即A类派生出B类,B类也可以派生出C类

三种类继承方式:

  1、public继承
  2、protected继承
  3、private继承
      public 成员可以通过对象来访问,private 成员不能通过对象访问。
      
protected 成员和 private 成员类似,也不能通过对象访问。但是当存在继承关系时,protected 和 private 就不一样了:基类中的 protected 成员可以在派生类中使用,而基类中的 private 成员不能在派生类中使用
      实际上:基类的 private 成员是能够被继承的,并且(成员变量)会占用派生类对象的内存,它只是在派生类中不可见,导致无法使用罢了。
      在派生类中访问基类 private 成员的唯一方法就是借助基类的非 private 成员函数,如果基类没有非 private 成员函数,那么该成员在派生类中将无法访问。

继承方式/基类成员public成员protected成员private成员
public继承 public protected 不可见
protected继承 protected protected 不可见
private继承 private private 不可见

  被继承的类看做是原材料,继承方式看做是加工条件;条件从苛刻到放松依次为:private继承  >  protected继承  >   public继承
public继承的条件最放松限制最小,private继承条件最苛刻限制最大;
    

更改访问权限:
  使用 using 关键字可以改变基类成员在派生类中的访问权限,但是using 只能改变基类中 public 和 protected 成员的访问权限,不能改变 private 成员的访问权限,因为基类中 private 成员在派生类中是不可见的,根本不能使用,所以基类中的 private 成员在派生类中无论如何都不能访问。

class People {
public:
    void show();
protected:
    char *m_name;
    int m_age;
};
//派生类Student
class Student : public People {
public:
    void learning();
public:
    using People::m_name;  //将protected改为public
    using People::m_age;  //将protected改为public
    float m_score;
private:
    using People::show;  //将public改为private
};

C++成员变量(成员函数)名的覆盖(遮蔽):

  如果派生类中新增一个成员变量(或成员函数),该成员变量(或成员函数)与基类中的成员变量(或成员函数)同名,则新增的成员变量(或成员函数)就会遮蔽从基类中继承过来的成员变量(或成员函数)
  被遮蔽了的基类的成员变量或成员函数并非是没有继承过来,而仅仅是被派生类的同名成员变量和成员函数给遮蔽了,调用的时候需要用到类名加上域解析操作符((被遮蔽的)类名::

 

C++间接继承:(继承具有传递定,亲缘关系)

  继承可以是直接继承,也可以是间接继承!
  假设C类继承B类,B类继承A类,相互联系的直接继承;C类还可以直接继承A类,跳过B类,变为间接继承。
  虽然可以理解间接继承,但间接继承所得的成员变量和成员函数,其属性遵循直接继承时的规则,亲缘关系的问题

 

C++继承机制下的构造函数———构造函数也能被继承,但派生类如果变异则需要先先执行基类构造函数,然后再去执行派生类构造函数

  派生类同样有构造函数,当派生出新的类后,创建的派生类的对象时,同样会调用构造函数进行初始化,用于初始化派生类从基类中继承过来的成员变量。而派生类中新增的成员变量则需要重新定义构造函数用于初始化了。
  创建派生类对象时,先由派生类构造函数调用基类构造函数,然后再执行派生类构造函数函数体中的内容,也就是说先执行基类构造函数,然后再去执行派生类构造函数
  创建对象时先是执行基类的构造函数,然后再是执行派生类的构造函数。构造函数的调用顺序是按照继承的层次,自顶向下,从基类再到派生类的。

 

 C++派生类构造函数调用规则

   派生类构造函数可以自动调用基类的默认构造函数,但是前提是默认构造函数必须存在。
  但如果我们在基类中定义了一个带参数的构造函数,那么基类就不会在生成默认构造函数,基类没有默认构造函数怎么办?|
解决方案:
    1、在基类中定义一个默认构造函数(不带参数的构造函数)                                                         源头处解决,从基类解决,源头止水,一劳永逸
    2、派生类每个构造函数都显式的调用(手动调用)基类中的带参构造函数(自己写的)              末节处解决,从派生类解决,亡羊补牢
  在创建派生类对象时,必须显式或隐式地调用基类的某一个构造函数,这一点非常重要。当然被调用的基类的构造函数可以是带参构造函数,也可以是默认构造函数。

 

C++继承机制下的析构函数

  创建派生类对象时,构造函数的调用顺序是按照继承顺序,先执行基类构造函数,然后再执行派生类的构造函数。但是对于析构函数,其调用顺序是正好相反的,即先执行派生类的构造函数,然后再执行基类的构造函数。
  每一个类中最多只能有一个析构函数,因此调用的时候并不会出现二义性,因此析构函数不需要显式的调用。

 

 

C++