zoukankan      html  css  js  c++  java
  • 从零开始学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的,则在类体外也可以使用“ 派生类对象.基类名::函数名(参数)”  的语法,也可用“ 派生类指针->基类名::函数名(参数)”的语法,同理被隐藏的数据成员也可以使用上述列举的方法访问。

    如果不属于上述的情况,则是一般的继承,则使用一般的访问语法即可。
  • 相关阅读:
    Java子类与父类的初始化
    悠哈牛奶糖为什么有五种味道单独装的,而不是混合装的
    C++ TinyXml操作(含源码下载)
    动物园海洋馆
    冰上行走
    Tmux : GNU Screen 的替代品
    考虑使用jruby
    关于一些展现的框架
    python抓取google搜索url
    pythonwebkit
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3186943.html
Copyright © 2011-2022 走看看