• 从零开始学C++之继承(一):公有/私有/保护继承、overload/overwrite/override之间的区别


    一、继承

    C++很重要的一个特征就是代码重用。在C语言中重用代码的方式就是拷贝代码、修改代码。C++可以用继承或组合的方式来重用。通过组合或继承现有的的类来创建新类,而不是重新创建它们。

    继承是使用已经编写好的类来创建新类,新的类具有原有类的所有属性和操作,也可以在原有类的基础上作一些修改和增补。
    新类称为派生类或子类,原有类称为基类或父类
    派生类是基类的具体化


    (一)、派生类的声明语法为:
    class 派生类名 : 继承方式  基类名
    {
               派生类新增成员的声明;
    }


    (二)、公有/私有/保护成员

    在关键字public后面声明,它们是类与外部的接口,任何外部函数都可以访问公有类型数据和函数。
    在关键字private后面声明,只允许本类中的函数访问,而类外部的任何函数都不能访问。
    在关键字protected后面声明,与private类似,其差别表现在继承与派生时对派生类的影响不同


    (三)、公有/私有/保护继承



    (四)、接口继承与实现继承

    我们将类的公有成员函数称为接口。
    公有继承,基类的公有成员函数在派生类中仍然是公有的,换句话说是基类的接口成为了派生类的接口,因而将它称为接口继承。
    实现继承,对于私有、保护继承,派生类不继承基类的接口。派生类将不再支持基类的公有接口,它希望能重用基类的实现而已,因而将它称为实现继承。


     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    #include <iostream>
    using  namespace std;

    class Base
    {
    public:
         int x_;
    protected:
         int y_;
    private:
         int z_;
    };

    class PublicInherit :  public Base
    {
    public:
         void Test()
        {
            x_ =  10;
            y_ =  20;
             //z_ = 30; error
        }
    private:
         int a_;
    };

    class PublicPublicInherit :  public PublicInherit
    {
    public:
         void Test()
        {
            y_ =  20;
        }
    };

    class PrivateInherit :  private Base
    {
    public:
         void Test()
        {
            x_ =  10;
            y_ =  20;
             //z_ = 30; error
        }
    };

    int main( void)
    {
        PublicInherit pub;
        pub.x_ =  20;

        PrivateInherit pri;
         //pri.x_ = 10; error
         return  0;
    }

    (五)、继承与重定义

    对基类的数据成员的重定义
    对基类成员函数的重定义分为两种

    overwrite(隐藏)

    override(覆盖)

    (六)、继承与组合

    无论是继承与组合本质上都是把子对象放在新类型中,两者都是使用构造函数的初始化列表去构造这些子对象。
    组合通中是在希望新类内部具有已存在的类的功能时使用,而不是希望已存在类作为它的接口。组合通过嵌入一个对象以实现新类的功能,而新类用户看到的是新定义的接口,而不是来自老类的接口。(has-a)
    如果希望新类与已存在的类有相同的接口(在这基础上可以增加自己的成员)。这时候需要用继承,也称为子类型化。(is-a)

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
     
    #include <iostream>
    using  namespace std;

    class Base
    {
    public:
        Base() : x_( 0), y_( 48)
        {

        }
         int GetBaseX()  const
        {
             return x_;
        }

         int GetBaseY()  const
        {
             return y_;
        }
         void Show()
        {
            cout <<  "Base::Show ..." << endl;
        }
         int x_;
    private:
         int y_;  //继承后无法被直接访问,可通过GetBaseY访问
    };

    class Derived :  public Base
    {
    public:
        Derived() : x_( 0)
        {

        }
         int GetDerivedX()  const
        {
             return x_;
        }
         void Show( int n) //与下面的show 构成重载,基类的show被隐藏
        {
            cout <<  "Derived::Show " << n << endl;
        }

         void Show()
        {
            cout <<  "Derived::Show ..." << endl;
        }
         int x_;  //重定义x_,基类的x_被隐藏
    };

    //组合关系
    class Test
    {
    public:
        Base b_;
         int x_;
    };

    int main( void)
    {
        Derived d;
        d.x_ =  10;
        d.Base::x_ =  20//访问被隐藏的基类x_;
        cout << d.GetBaseX() << endl;
        cout << d.GetDerivedX() << endl;
        cout << d.GetBaseY() << endl;

        d.Show();
        d.Base::Show(); //访问被隐藏的基类show

        cout <<  sizeof(Derived) << endl;
        cout <<  sizeof(Test) << endl;

         return  0;
    }



    下面总结一下overload/overwrite/override 之间的区别:

    成员函数被重载(overload)的特征:
    (1)相同的范围(在同一个类中);
    (2)函数名字相同;
    (3)参数不同;
    (4)virtual关键字可有可无。

    覆盖(override)是指派生类函数覆盖基类函数,特征是:
    (1)不同的范围(分别位于派生类与基类);
    (2)函数名字相同;
    (3)参数相同;
    (4)基类函数必须有virtual关键字。

    隐藏(overwrite)(派生类与基类)
    (1)不同的范围(分别位于派生类与基类);
    (2)函数名与参数都相同,无virtual关键字
    (3)函数名相同,参数不同,virtual可有可无

    当隐藏发生时(实际上是继承了但不可见),如果在派生类的成员函数中想要调用基类的被隐藏函数,可以使用
    “ 基类名::函数名(参数)”的语法形式,如果被隐藏的函数是public的,则在类体外也可以使用“ 派生类对象.基类名::函数名(参数)”  的语法,也可用“ 派生类指针->基类名::函数名(参数)”的语法,同理被隐藏的数据成员也可以使用上述列举的方法访问。

    如果不属于上述的情况,则是一般的继承,则使用一般的访问语法即可。
  • 相关阅读:
    HDU 2955 Robberies(01背包)
    HDU 2602 Bone Collector(01背包)
    HUST 1352 Repetitions of Substrings(字符串)
    HUST 1358 Uiwurerirexb jeqvad(模拟解密)
    HUST 1404 Hamming Distance(字符串)
    HDU 4520 小Q系列故事――最佳裁判(STL)
    HDU 2058 The sum problem(枚举)
    【破解】修改程序版权、添加弹窗
    HDU 1407 测试你是否和LTC水平一样高(枚举)
    HDU 1050 Moving Tables(贪心)
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3186943.html
Copyright © 2020-2023  润新知