zoukankan      html  css  js  c++  java
  • 继承和多态一(转)

    第3章 继承与多态

    面向对象的三大特征:封装,继承,多态。

    3.1 继承

    3.1.1 继承的概念

    注意: 
    1. 基类的构造函数、拷贝构造函数和析构函数不可以被继承。 
    2. 派生类继承了基类的全部数据成员和除了构造、析构函数之外的所有成员函数。派生类对于基类成员的继承是没有选择的,不能选择接收或舍弃基类中的某些成员。 
    3. 派生类中除了与基类同名的成员外还可以添加新成员,用于实现新功能,保证派生类的功能在基类的基础上的发展。 
    4. 多个派生类可以继承自一个基类。 
    5. C++中可以通过派生形成类的层次结构,即一个基类可以是另一个更高层次类的派生类,而另一个派生类也可以继续产生派生类。

    3.1.2 继承权限

    总结出不同情况下的访问权限:

    注意虽然继承的方法分为公有继承、私有继承、保护继承,默认为private(这一点也是class和struct的区别,struct默认是public继承),但不管哪种继承,派生类仅可以访问基类中所有的非私有成员,但我们可以通过基类的公有和保护成员访问它的私有成员,这是封装的重要概念,同时达到了数据抽象的效果。

    (1)公有继承:基类的公有也是派生类的公有,基类的保护也是派生类的保护,基类的私有不能继承;

    (2)私有继承:基类的公有和保护成为派生类的私有成员;

    (3)保护继承:基类的公有和保护成为派生类的保护成员;

    3.1.3 派生类操作基类对象的四种方法

    1.派生类对象可以向基类对象赋值。(单项的,不可逆) 
    2.派生类对象可以替代基类对象向基类对象的引用进行赋值或初始化。

    ClassA obj_a;
    ClassB obj_b;
    ClassA &refa = obj_a;//可以将这一行改为 ClassA &refa = obj_b; 

    3.如果函数的参数是基类对象或基类对象的引用,函数调用时的实参可以是派生类对象。

    void func(ClassA &ref)
    {
        cout<<ref.num<<endl;
    }

    在调用func()函数时可以用派生类ClassB的对象obj_b作实参:

    func(obj_b);

    4.派生类对象的地址可以赋值给基类指针变量。

    3.2 派生类

    3.2.1 构造函数

    派生类中定义带参数构造函数的形式如下所示:

    派生类名::派生类构造函数名(参数列表):基类构造函数名(基类构造函数参数表)
    {
        派生类新增成员的初始化语句
    }

    3.2.2 析构函数

    若派生类中没有显式的定义析构函数,编译系统会提供一个默认的析构函数。显式定义中,对象生命周期结束时会先调用派生类的析构函数,再调用基类的析构函数。

    3.2.3 隐藏基类函数

    派生类中重新定义基类同名函数的方法,称为对基类函数的覆盖或改写,覆盖后基类同名函数在派生类中被隐藏。定义派生类对象调用该函数时,调用的是自身的函数,基类同名函数不被调用。

    3.3 多重继承

    3.3.1 声明多重继承的方式

    class 派生类名:继承方式 基类1名称,继承方式 基类2名称,...
    {
        public:
            新增加的公有成员
        protected:
            新增加的保护成员
        private:
            新增加的私有成员
    }

    3.3.2 多重继承派生类的构造函数

    定义:

    派生类名::派生类构造函数名(参数总表):基类1构造函数名(参数表1),基类2构造函数名(参数表2),...
    {
        派生类构造函数体
    }

    假如派生类是多重继承,并且新增数据成员有一个或多个对象成员,那么派生类需要初始化的数据有三部分:继承的数据成员、新增类的数据成员、新增普通成员。 
    这种复杂派生类定义:

    派生类名::派生类构造函数名(参数总表):基类1构造函数名(参数表1),基类2构造函数名(参数表2),...子对象名1(参数表n),子对象名2(参数表n+1)
    {
        派生类构造函数体
    }

    派生类构造函数调用顺序: 
    首先,调用基类构造函数。 
    其次,调用对象成员的构造函数。 
    最后,调用派生类的构造函数。

    3.3.3 多重继承引起的二义性

    1. 调用不同基类中的同名成员时产生的二义性 
      消除方法: 
      (1)使用作用域限定符 
      (2)派生类中定义与基类同名函数,将基类函数隐藏
    2. 派生类中访问公有成员时产生二义性

    3.3.4 虚基类

    在多重继承中,若一个类声明为虚基类,则能保证一个派生类间接地多次继承该类时,派生类中只继承该基类的一份成员,避免了派生类中访问公共基类公有属性多份拷贝的二义性,其效果等同于将基类函数隐藏的方法(上文3.3.3和3.2.3)。 
    定义:

    class 派生类名:virtual 继承方式  基类名
    {
        派生类成员
    };

    3.4 多态

    3.4.1 多态性概念

    3.4.2 虚函数

    虚函数是运行时多态,若某个基类函数声明为虚函数,则其公有派生类将定义与其基类虚函数原型相同的函数,这时,当使用基类指针或基类引用操作派生类对象时,系统会自动用派生类中的同名函数代替基类虚函数。 
    声明形式:

    class 类名
    {
        virtual 函数返回值类型  函数名(参数表)
    }
    1. 一般虚函数成员 
      带有虚函数时,C++编译器的操作步骤: 
      (1)为各个类建立虚函数列表,若无虚函数则不操作。 
      (2)暂不连接虚函数,只是将各个虚函数地址放入虚函数表。 
      (3)连接各静态函数。
    2. 虚析构函数

    3.4.3 纯虚函数

    在定义一个表示抽象概念的类时,有时无法或者不需要给出某些成员函数的具体实现,函数的实现在派生类中完成,基类中这样的函数声明为纯虚函数。 
    与虚函数相比,纯虚函数没有函数体,其作用是在基类中为派生类保留一个接口,方便派生类根据需要对它实现,实现多态。 
    声明形式:

    virtual 函数返回值类型  函数名(参数表)= 0 ; 

    3.5 抽象类与内部类

    3.5.1 抽象类

    如果一个类中至少包含一个纯虚函数,则该类成为抽象类,因此抽象类是基于纯虚函数的。 
    定义形式:

    class 类名
    {
        public:
        virtual 函数返回值类型  函数名(参数表)= 0;
        其他函数声明
    }

    3.5.2 内部类

    class 外部类名
    {
        外部类成员;
    访问限定符:
        class 内部类名
        {
            内部类成员
        };
    };
    我们都在通往真理的路上。
  • 相关阅读:
    Spring Boot----处理异常
    Spring Boot----SpringBoot中SpringMVC配置原理
    git----常见问题
    源码分析----Mybatis
    spring----一些xml配置
    Spring MVC----spring MVC 异常处理
    java----小游戏
    java----垃圾回收机制
    java----常见jar包
    anconda安装
  • 原文地址:https://www.cnblogs.com/cvtoEyes/p/8488898.html
Copyright © 2011-2022 走看看