C++_继承与派生类

继承与派生类

  • 面向对象4个特征:抽象、封装、继承、多态
  • 继承目的: 代码的重用和代码的扩充
  • 继承方法程序设计思路: 一般->特殊
  • 继承种类: 单继承、多继承
  • 基本概念: 基类(父类)、派生类(子类)
  • 继承方式: public protected private
  • 继承内容: 除构造函数、析构函数、私有成员外的其他成员
  • 重点掌握内容:继承方式及访问规则、构造函数定义

1 继承的概念

2个过程:

  • 保持已有类的特性而构造新类的过程称为继承
  • 在已有类的基础上新增自己的特性而产生新类的过程称为派生

2个概念:

  • 被继承的已有类称为基类(或父类)
  • 派生出的新类称为派生类

2. 继承与派生的目的

  • 继承的目的:实现代码重用。(站在巨人的肩膀上)
  • 派生的目的:当新的问题出现,原有程序无法解决(或不能完全解决)时,需要对原有程序进行改造。(创新)

(1) 修改基类成员

在派生类中声明了一个与基类成员同名的新成员。在派生类作用域内或者在类外通过派生类的对象直接使用这个成员名,只能访问到派生类中声明的同名新成员,即新成员覆盖了从基类继承的同名成员,称为同名覆盖。

(2) 描述新的特征或方法。

区分“重载(描述新的特征和方法)”和“重写(同名覆盖)”

为什么要使用继承
class person {
protected:
    char name[10];
    int age;
    char sex;
public:
    void print();
};
class employee{
protected:
    char name[10];
    int age;
    char sex;
    char department[20];
    float salary;
public:
    print();
};
派生类的声明
//定义一个基类
class person{
protected:
    char name[10];
    int age;
    char sex;
public:
    //……
};
//定义一个派生类
class employee:public person {
protected:
    char department[20];
    float salary;
public:
    //……
};

3. 继承的访问控制

派生类继承了基类中除构造函数和析构函数之外的所有成员。

派生类的成员包括:

  • (1)继承基类的成员
  • (2)派生类定义时声明的成员。

从已有类派生出新类时,可以在派生类内完成以下几种功能:

  • (1) 可以增加新的数据成员;
  • (2) 可以增加新的成员函数;
  • (3) 可以重新定义基类中已有的成员函数;
  • (4) 可以改变现有成员的属性。

基类成员在派生类中的访问属性与继承方式有关。

声明一个派生类的一般格式为:

class 派生类名:继承方式 基类名
{
    //派生类新增的数据成员和成员函数
};
由类person继承出类employee的三种格式:
  • (1) 公有继承
class employee:public person{
//…
};
  • (2) 私有继承(系统默认为私有继承)
class employee:private person{
//…
};
  • (3) 保护继承
class employee:protected person{
//…
};

三种继承方式:

  • 公有继承(public)
  • 私有继承(private)
  • 保护继承(protected)

派生类成员的访问权限

  • 1)inaccessible(不可访问)
  • 2)public
  • 3)private
  • 4)protected

基类成员在派生类中的访问属性

在基类中的访问属性 继承方式 在派生类中的访问属性
private public 不可直接访问
private private 不可直接访问
private protected 不可直接访问
public public public
public private private
public protected protected
protected public protected
protected private private
protected protected protected

派生类对基类成员的访问规则

派生类对基类成员的访问形式主要有以下两种:

(1) 内部访问: 由派生类中新增成员对基类继承来的成员的访问。

(2) 对象访问: 在派生类外部,通过派生类的对象对从基类继承来的成员的访问。

不同继承方式决定的不同访问控制权限体现在:
1、派生类成员对继承于基类的成员的访问控制。
2、派生类对象对继承于基类的成员的访问控制。

1. 私有继承的访问规则

基类的 public成员protected成员 被继承后作为派生类的 private成员,派生类的其他成员可以直接访问它们,但是在类外部通过派生类的对象无法访问。

基类的 private成员 在私有派生类中是不可直接访问的,所以无论是派生类成员还是通过派生类的对象,都无法直接访问从基类继承来的private成员,但是可以通过基类提供的 public成员函数 间接访问。

通过派生类的对象不能访问基类中的任何成员。

例 私有继承举例
class Rectangle: private Point { //派生类声明
public: //新增外部接口
    void InitR(float x, float y, float w, float h)
    {InitP(x,y);W=w;H=h;} //访问基类公有成员
    void Move(float xOff, float yOff) {Point::Move(xOff,yOff);}
    float GetX() {return Point::GetX() ;}
    float GetY() {return Point::GetY() ;}
    float GetH() {return H;}
    float GetW() {return W;}
private: //新增私有数据
    float W,H;
};
#include<iostream.h>
#include<math.h>
int main(){ //通过派生类对象只能访问本类成员
    Rectangle rect;
    rect.InitR(2,3,20,10);
    rect.Move(3,2);
    cout<<rect.GetX() <<','
    <<rect.GetY() <<','
    <<rect.GetH() <<','
    <<rect.GetW() <<endl;
    return 0;
}
说明

通过私有派生,基类的任何成员在派生类中都是私有的,这样就改变了基类中公有成员(以及保护成员)在派生类中的访问权限。

这样一来,派生类中继承来的基类成员均成为它的私有成员,使得通过这个派生类再次派生出新类时,这些成员在新派生类中均成为不可访问成员,使派生类的使用很不方便。所以私有派生在实用中用得不多。

2. 公有继承的访问规则

基类的 public成员protected成员 被继承到派生类中仍作为派生类的 public成员protected成员,派生类的其他成员可以直接访问它们。但是,类的外部使用者只能通过派生类的对象访问继承来的public成员。

基类的 private成员 在私有派生类中是不可直接访问的。所以无论是派生类成员还是通过派生类的对象,都无法直接访问从基类继承来的private成员,但是可以通过基类提供的 public成员函数 间接访问它们。

派生类的对象只能访问基类的public成员。

公有继承举例
class Point { //基类 Point类的声明
public: //公有函数成员
    void InitP(float xx=0, float yy=0)
    {X=xx;Y=yy;}
    void Move(float xOff, float yOff)
    {X+=xOff;Y+=yOff;}
    float GetX() {return X;}
    float GetY() {return Y;}
private: //私有数据成员
    float X,Y;
protected: //受保护数据成员
    int a,b;
};
class Rectangle: public Point { //派生类声明
public: //新增公有函数成员
    void InitR(float x, float y, float w, float h)
    {InitP(x,y);W=w;H=h;}//调用基类公有成员函数
    float GetH() {return H;}
    float GetW() {return W;}
private: //新增私有数据成员
    float W,H;
};
#include<iostream.h>
#include<math.h>
int main()
{
    Rectangle rect;
    rect.InitR(2,3,20,10); //通过派生类对象访问基类公有成员
    rect.Move(3,2);
    cout<< rect.GetX() <<','
    << rect.GetY() <<','
    << rect.GetH() <<','
    << rect.GetW() <<endl;
    return 0;
}
说明
  • 一个派生类的基类成员是 私有成员的时候,虽然基类的成员已被派生类继承,但C++规定,这个派生类仍不能直接访问基类的私有成员,只能通过基类的公有成员作为接口去访问,这是符合数据封装的思想的。基类的私有成员在派生类中就是“不可访问(inaccessible)成员”
  • 为了能够在派生类中访问基类所有成员,又使数据封装得以实现,就引入了"保护成员"的概念。就是在类的定义中,用protected来说明类成员,而不是用"private",这样的成员就是类的保护成员。保护成员对于派生类的成员函数而言是公有成员,而对于其他函数就仍是私有成员。
  • 在公有派生的情况下,每一个派生类的对象都是基类的一个对象(它继承了基类的所有的成员并没有改变其访问权限)
    • 派生的对象可以赋给基类的对象。 如: (约定derived是从类base公有派生而来的)
    derived d;
    base b;
    b=d;
    
    • 派生类的对象可以初始化基类的引用。
    derive d;
    base &br=d;
    
    • 派生类的对象的地址可以赋给指向基类的指针。
    derived d;
    base *pb=&d;
    
    • 在后两种情况下,通过指针或引用只能访问对象d中所继承的基类成员。
例子
class base{
public: 
    test1(){cout << "test1:base"<<endl;}
};
class derived : public base {
public:
    test2(){cout << "test2:derived"<<endl;}
};
void main()
{
    derived d; base &b = d;
    b.test2();
    b.test1();
}

3. 保护继承的访问规则

基类的 public成员protected成员 被继承到派生类中都作为派生类的 protected成员,派生类的其他成员可以直接访问它们,但是类的外部使用者不能通过派生类的对象来访问它们。

基类的 private成员 在私有派生类中是不可直接访问的,所以无论是派生类成员还是通过派生类的对象,都无法直接访问基类的 private成员

通过派生类的对象不能访问基类中的任何成员

protected 成员的特点与作用
  • 对建立其所在类对象的模块来说(水平访问时),它与 private 成员的性质相同。
  • 对于其派生类来说(垂直访问时),它与 public 成员的性质相同。
  • 既实现了数据隐藏,又方便继承,实现代码重用。
例 保护继承举例
class Rectangle: protected Point { //派生类声明
public: //新增外部接口
    void InitR(float x, float y, float w, float h)
    {InitP(x,y);W=w;H=h;} //访问基类公有成员
    void Move(float xOff, float yOff) {Point::Move(xOff,yOff);}
    float GetX() {return Point::GetX() ;}
    float GetY() {return Point::GetY() ;}
    float GetH() {return H;}
    float GetW() {return W;}
private: //新增私有数据
    float W,H;
};

4. 基类与派生类的关系

1.派生类是基类的具体化

类的层次通常反映了客观世界中某种真实的模型。如,定义输入设备为基类,而键盘、鼠标和数字化板将是派生类。

2.派生类是基类定义的延续

先定义一个抽象基类,该基类中有些操作并未实现。然后定义非抽象的派生类,实现抽象基类中定义的操作。后面要讲述的虚函数就属此类情况。这时,派生类是抽象的基类的实现,即可看成是基类定义的延续。这也是派生类的一种常用的方法。

3.派生类是基类的组合

在多继承时,一个派生类有多于一个的基类,这时派生类将是所有基类行为的组合。

派生类将其本身与基类区别开来的方法是添加数据成员和成员函数。因此,继承的机制将使得在创建新类时,只需说明新类与已有类的区别,从而大量原有的程序代码都可以复用,所以有人称类为“可复用的软件构件”。

posted @ 2020-02-27 23:57  鲸90830  阅读(323)  评论(0)    收藏  举报