C++_16_继承和派生 - 重写版

C++继承和派生

继承和派生的概念:

  继承和派生 是 “类” 和 “类” 之间的关系,描述的是从一个类到另一个类的过程,继承和派生是描述的同一个过程,只不过看待的角度不同
  先出现的类是父类或基类,后生成的类是子类
    继承:子类到父类叫做继承
    派生:父类到子类叫做派生
  由于派生类可以将基类的代码继承过来,无需重新设计,因而继承解决了代码重用的问题,大大提高了软件的开发效率。同时如果这些代码在基类中运行无误,则继承之后到派生类中运行也是不会有问题的。
  派生和继承可以叠加嵌套,即A类派生出B类,B类也可以派生出C类

 

//前面学的一大堆都是封装
//现在开始学习第二板块--继承和派生
#include<iostream>
using namespace std;
class html        //父类
{
public:
    void headhtml(void)
    {
        cout << "网页头部" << endl;
    }
    void lefthtml(void)
    {
        cout << "左侧栏" << endl;
    }
    void mainhtml(void)
    {
        cout << "网页主题" << endl;
    }
    void endhtml(void)
    {
        cout << "网页底部" << endl;
    }
private:
};

class ithtml :public html   //子类ithtml公有制继承于父类html
{
public:
    //除了继承出来的完全一样的成员,还可以尽快客制化自己的成员
    void selfhtml(void)    
    {
        cout << "个人网页" << endl;
    }
};

int main()
{
    ithtml it;
    it.headhtml();    //继承而来的成员函数
    it.mainhtml();
    it.lefthtml();
    it.endhtml();
    it.selfhtml();    //客制化自己的成员函数
    return 0;
}

 

三种类继承方式:

  1、public继承
  2、protected继承
  3、private继承
      public 成员可以通过对象来访问,private 成员不能通过对象访问。
      protected 成员和 private 成员类似,也不能通过对象访问。但是当存在继承关系时,protected 和 private 就不一样了:基类中的 protected 成员可以在派生类中使用,而基类中的 private 成员不能在派生类中使用
  实际上:
  1、子类继承父类, 子类拥有父类中(除了构造和析构之外)全部成员变量和成员方法;包括公有、保护、私有成员变量和函数,但是不包含构造和析构,因为这个独立类特有的,不在可继承范围内。
  2、基类的 哪怕是 private 成员是能够被继承的,并且(成员变量)会占用派生类对象的内存,它只是在派生类中不可见,无法访问罢了。
  3、在派生类中访问基类 private 成员的唯一方法就是借助基类的非 private 成员函数,如果基类没有非 private 成员函数,那么该成员在派生类中将无法访问。

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

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

单继承:指每个派生类只直接继承了一个基类的特征   (一个父类 派生出 一个子类)
多继承:指多个基类派生出一个派生类的继承关系,多继承的派生类直接继承了不止一个基类的特征(多个父类  派生出 一个子类)

 

继承的内层结构:
Developer Command Prompt for VS 2022
  内层结构:cl d1 reportSingleClassLayout(继承的类名) test.cpp


更改访问权限:
  使用 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++继承机制下的析构函数

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

 

 继承中的构造和析构顺序 

   构造顺序: 父类(基类)构造 ------> 子类(派生类)构造
   析构顺序:子类(派生类)析构------> 父类 (基类) 析构

子类中 有父类、对象成员 构造和析构的顺序  

                 

 父类和子类的同名 成员变量 处理
  1、当 父类和子类 成员变量同名时  在子类就近原则 选择本作用域的子类成员
  2、如果在子类中 必须使用父类中的同名成员  必须加上父类的作用域。
  3、子类可以借助 父类的公有方法 间接的操作 父类的私有数据(不可见的数据)

 

父类和子类的同名 成员函数 处理
  在子类继承了父类的成员函数后,父类和子类成员函数同名,使用子类定义一个对象;
  如果子类自己再将同名成员重新进行定义,那么将使用子类的成员函数,父类同名成员函数将会被屏蔽;
  否者,如果子类没有再将同名成员函数进行定义,则会默认使用的仍旧是父类的成员函数;

子类中 有父类、对象成员 构造和析构的顺序
posted @ 2023-11-05 23:16  尘落曦枫  阅读(12)  评论(0编辑  收藏  举报