1.派生类的声明方式

    • 声明派生类的一般形式为:

    class **派生类名: [继承方式] 基类名
    {
    派生类新增加的成员
    } ; **

    • 例:假设已经声明了一个基类Student,在此基础上通过单继承建立一个派生类Student1

      1. class Student1: public Student//声明基类是Student
      2. {public:
      3. void display_1( ) //新增加的成员函数
      4. {cout<<″age: ″<<age<<endl;
      5. cout<<″address: ″<<addr<<endl;}
      6. private: int age; //新增加的数据成员
      7. string addr; //新增加的数据成员
      8. };
    • 继承方式包括

      • public(公用的)
      • private(私有的)
      • protected(受保护的)
      • 如不填写此项,则默认为private(私有的)



    2.派生类**的构成**

    • 派生类中的成员包括两大部分:
      • 一部分是从基类继承来的成员,
      • 另一部分是在声明派生类时增加的部分。
      • 每一部分均分别包括数据成员和成员函数。

    image.png

    • 构造一个派生类
    1. 从基类接收成员。派生类把基类全部的成员(不包括构造函数和析构函数)接收过来,不能选择接收其中一部分成员,而舍弃另一部分成员。
    2. 调整从基类接收的成员。接收基类成员是程序人员不能选择的,但是程序人员可以对这些成员作某些调整。
    3. 在声明派生类时增加的成员。这部分内容体现了派生类 对基类功能的扩展。
      • 声明派生类时,一般还应当自己定义派生类的构造函数和析构函数,因为构造函数和析构函数是不能从基类继承的。

    3.派生类成员的访问属性

    • 对基类成员和派生类自己增加的成员是按不同的原则处理的。具体为:
    1. 基类的成员函数访问基类成员。

    **

    1. 派生类的成员函数访问派生类自己增加的成员。

    **

    1. 基类的成员函数只能访问基类的成员,而不能访问派生类的成员。

    1. 派生类的成员函数访问基类的成员。

    **

    1. 在派生类外可以访问派生类的公用成员,而不能访问派生类的私有成员。

    • 如何确定基类成员在派生类中的访问属性?
      • 根据两个因素决定基类成员在派生类中的访问属性:
        • 基类成员所声明的**基类访问属性 **
        • 派生类所声明的对**基类的继承方式**,不同的继承方式决定了基类成员在派生类中的访问属性。


    4.公用继承**

    • 在定义一个派生类时将基类的继承方式指定为public的,称为公用继承 。
    • 用公用继承方式建立的派生类称为公用派生类(public derived class),其基类称为公用基类(public base class)。
    • 采用公用继承方式时
      • 基类的公用成员和保护成员在派生类中仍然保持其公用成员和保护成员的属性
      • 基类的**私有成员在派生类中并没有成为派生类的私有成员它仍然是基类的私有成员,只有基类的成员函数可以引 用它,而不能被派生类的成员函数引用,因此就成为派生类中的不可访问的成员**。
    • 例:访问公有基类的成员

      Class Student//声明基类
      {public: //基类公用成员 
        void get_value( )
      {cin>>num>>name>>sex;} 
      void display( ) 
      {cout<<″ num: ″<<num<<endl;
      cout<<″ name: ″<<name<<endl;
      cout<<″ sex: ″<<sex<<endl;
      }
      private : //基类私有成员 
      int num; 
      string name;
      char sex;
      };
      class Student1: public Student
      {
      public: 
      void display_1( )
      {cout<<″ num: ″<<num<<endl; //引用基类的私有成员,错误
      cout<<″ name: ″<<name<<endl; //引用基类的私有成员,错误
      cout<<″ sex: ″<<sex<<endl; //引用基类的私有成员,错误 
      cout<<″ age: ″<<age<<endl; //引用派生类的私有成员,正确 
      cout<<″ address: ″<<addr<<endl;} //引用派生类私有成员,正确
      private: 
      int age;
      string addr;
      };
      
      • 可以将派生类Student1的声明改为

        class Student1: public Student 
        {public: 
        void display_1( )
        {
        stud.display( ); 
        cout<<″ age: ″<<age<<endl; //引用派生类的私有成员,正确 
        cout<<″ address: ″<<addr<<endl; //引用派生类的私有成员,正确
        }
        private:
        int age; 
        string addr;
        };
        
        • 实际上,可以在派生类的display_1函数中调用基类的display函数,在主函数中只要写一行:stud.display_1();



    5.**私有继**承

    • 在声明一个派生类时将基类的继承方式指定为private的, 称为私有继承 ;
    • 用私有继承方式建立的派生类称为私有派生类(private derived class) ,其基类称为私有基类(private base class)。
    • 私有基类的公用成员和保护成员在派生类中的访问属性相当于派生类中的私有成员,即派生类的成员函数能访问它们,而在派生类外不能访问它们。
    • 私有基类的私有成员在派生类中成为不可访问的成员,只有基类的成员函数可以引用它们。
    • 一个基类成员在基类中的访问属性和在派生类中的访问属性可能是不同的。
    • 对于不需要再往下继承的类可以用私有继承方式把它隐蔽起来,这样,下一层的派生类无法访问它的任何成员。

                           ![image.png](https://cdn.nlark.com/yuque/0/2020/png/2314091/1598074763607-bd78737a-2c41-450d-bce6-ff57628e80d1.png#align=left&display=inline&height=220&margin=%5Bobject%20Object%5D&name=image.png&originHeight=440&originWidth=845&size=76177&status=done&style=none&width=422.5)
      
    • 例:公用继承方式改为用私有继承方式

      Class Student//声明基类
      {public: //基类公用成员 
        void get_value( )
      {cin>>num>>name>>sex;} 
      void display( ) 
      {cout<<″ num: ″<<num<<endl;
      cout<<″ name: ″<<name<<endl;
      cout<<″ sex: ″<<sex<<endl;
      }
      private : //基类私有成员 
      int num; 
      string name;
      char sex;
      };
      class Student1: private Student//用私有继承方式声明派生类Student1
      {public: void display_1( ) //输出两个数据成员的值 
      {cout<<″age: ″<<age<<endl; //引用派生类的私有成员,正确
      cout<<″address: ″<<addr<<endl;} //引用派生类的私有成员,正确 
      private:
      int age;
      string addr;
      };
      int main( )
      {Student1 stud1;//定义一个Student1类的对象stud1
      stud1.display(); //error
      stud1.display_1( );
      stud1.age=18; //error
      return 0;
      }
      
      • 说明
        • 不能通过派生类对象引用从私有基类继承过来的任何成员。
        • 派生类的成员函数不能访问私有基类的私有成员,但可以访问私有基类的公用成员。
    • 有没有办法调用私有基类的公用成员函数,从而引用私有基类的私有成员呢?

      • 虽然在派生类外不能通过派生类对象调用私有基类的公用成员函数, 但可以**通过派生类的成员函数调用私有基类的公用成员函数**(此时它是派生类中的私有成员函数,可以被派生类的任何成员函数调用)。
      • 例:
        void display_1( )
        {display():
        cout<<″age: ″<<age<<endl;
        cout<<″address: ″<<addr<<endl;}
        int main( )
        {Student1 stud1;
        stud1.display_1( ); 
        return 0;}
        
    • 由于私有派生类限制太多,使用不方便,一般不常使用。

    6.包含成员和保护继承

    • 由protected声明的成员称为 “保护成员”。
    • 从类的用户角度来看,保护成员等价于私有成员。与私有成员不同,保护成员可以被派生类的成员函数引用。

                                  ![image.png](https://cdn.nlark.com/yuque/0/2020/png/2314091/1598075422195-6d4e1569-5dd1-4e57-90b7-b37c6b36b369.png#align=left&display=inline&height=170&margin=%5Bobject%20Object%5D&name=image.png&originHeight=310&originWidth=633&size=67144&status=done&style=none&width=347)
      
    • 在定义一个派生类时将基类的继承方式指定为protected的, 称为保护继承

    • 用保护继承方式建立的派生类称为保护派生类(protected derived class),其基类称为受保护的基类(protected base class),简称保护基类。
    • 保护继承的特点
      • 保护基类的公用成员和保护成员在派生类中都成了保护成员;
      • 私有成员仍为基类私有。
      • 书中表11.3
    • 保护成员和私有成员不同之处,在于把**保护成员的访问范围扩展到派生类中**。
    • 私有继承和保护继承方式在使用时需要十分小心,很容易搞错,一般不常用。
    • 例:在派生类中引用保护成员
      #include <iostream>
      #include <string>
      using namespace std;
      class Student//声明基类 
      {public: //基类公用成员 
      void display( );
      protected : //基类保护成员 
      int num;
      string name;
      char sex;
      };
      void Student::display( ) //定义基类成员函数 
      {cout<<″num: ″<<num<<endl;
      cout<<″name: ″<<name<<endl;
      cout<<″sex: ″<<sex<<endl;
      }
      class Student1: protected Student //用protected方式声明派生类Student1
      {public: void display1( ); //派生类公用成员函数 
      private: int age; //派生类私有数据成员 
      string addr; //派生类私有数据成员 };
      void Student1::display1( ) //定义派生类公用成员函数 
      {cout<<″num: ″<<num<<endl; //引用基类的保护成员,合法 
       cout<<″name: ″<<name<<endl; //引用基类的保护成员,合法 
       cout<<″sex: ″<<sex<<endl; //引用基类的保护成员,合法 
       cout<<″age: ″<<age<<endl; //引用派生类的私有成员,合法 
       cout<<″address: ″<<addr<<endl; //引用派生类的私有成员,合法
      } 
      int main( )
      {Student1 stud1; //stud1是派生类Student1类的对象 
       stud1.display1( ); //合法,display1是派生类中的公用成员函数 
       stud1.num=10023; //错误,外界不能访问保护成员 
       return 0;
      }