• 7、继承



    1.继承

        儿子继承父亲的遗产,儿子拥有父亲所有的成员变量和成员函数。儿子也可以拥有父亲没有的成员变量和成员函数。

        子类与父类继承的关系,

        也就是说:

        (1)子类拥有父类所有的成员变量和成员函数(除了构造函数和析构函数)。

        (2)子类的对象可以当作父类的对象使用(认为子类是特殊的一个父类)

        (3)子类可以用父类没有的成员变量和成员函数。

    class Parent
    {
    public:
        Parent();
        ~Parent();
        void pri();
    private:
        int a;
    };
    Parent::Parent()
    {
        a = 100;
    }
    Parent::~Parent()
    {
    }
    void Parent::pri()
    {
        cout << "a = " << a << endl;
    }
    class Child : public Parent // 继承父类
    {
    };
    int main()
    {
        Parent p1;
        p1.pri();
        Child c1;
        c1.pri();
        while (1);
    }

        都可以打印出  a = 100;,这里就涉及到继承的方式的问题:

    class 子类名 : 继承的方式 父类名
    {
    }

        当没有指定 继承的方式(public,private)的话,那么就是默认为私有的继承。

    继承的权限:

    继承的方式

    public 父类在子类中,保持原有的访问的级别,子类可以访问父类的共有成员,私有成员不能被访问

    private 父类在子类中,全部变为private的访问级别,那么子类不可以访问父类所有的成员

        一般来说,我们都是 public 的方式进行继承,但是 private 成员可以被子类继承,但是不能被子类访问,所以,就有了了继承的关键字:protected

    关键字 protected:

        介于 private 和 public 之间,也就是说,被 protected 修饰的变量:

        (1)可以在类内被访问

        (2)可以被子类访问

        (3)不可以被外接(通过对象,不管是父类还是子类都不可以被访问)访问

    class Parent
    {
    public:
        Parent();
        ~Parent();
        void pri();
    protected: // 被保护的,子类就可以访问
        int a;
    };
    Parent::Parent()
    {
        a = 100;
    }
    Parent::~Parent()
    {
    }
    void Parent::pri()
    {
        cout << "a = " << a << endl;
    }
    class Child : public Parent // 继承父类
    {
    protected: //
        int b;
    public:
        void setDATA(int a, int b)
        {
            this->a = a;
            this->b = b; // b 是被保护的,所以可以被子类访问
        }
        void cintData()
        {
            cout << "a = " << a <<"   "<< "b = " << b << endl;
        }
    };
    int main()
    {
        Parent p1;
        
        p1.pri();
        Child c1;
        c1.setDATA(1, 2);
        c1.cintData();
        while (1);
    }

        如果不是被 protected 修饰,而是被 private 修饰的话,那么子类压根就没有权限去访问父类的 private 的成员变量,这个就不是我们想看到的,

    权限的设置:

    (1)需要被外接访问,则使用 public

    (2)只能在类内被访问的成员的话,则是设置为 private

    (3)只能在当前类内和子类中的访问的成员,则是设置为 protected

    c1a0d196-7b43-4305-b501-eee813009900

    继承成员对外的访问的属性: MAX(继承的方式,父类的访问的级别)

    继承访问级别设置的原则:

    需要被外接(对象)访问的成员直接设置为: public

    只能在类的内部被访问的成员设置为 : private

    只能在当前类和子类中访问的成员设置为 : protected

    继承中的构造和析构函数:

        子类和父类的继承,那么子类已经是继承了父类所有的成员函数和成员变量(除了构造函数和析构函数、拷贝构造函数、operator函数、友元函数没有被继承、)。

    子类的对象构造的时候,会调用父类的构造函数。父类的构造函数完成父类的构造,而子类的构造函数则是完成自己新增的成员进行初始化;因此析构的函数也是一样的,子类的就析构自己的就可以,继承的东西,就让父类的析构函数自己去完成清理的工作。

    class Parent
    {
    public:
        Parent();
        ~Parent();
    private:
    };
    Parent::Parent()
    {
        cout << "ia= am parent gouzao" << endl;
    }
    Parent::~Parent()
    {
        cout << "ia= am parent xigou" << endl;
    }
    class Child : public Parent
    {
    public:
        Child ();
        ~Child ();
    private:
    };
    Child :: Child()
    {
        cout << "ia= am Child gouzao" << endl;
    }
    Child ::~Child()
    {
        cout << "ia= am Child xigou" << endl;
    }
    void run()
    {
        Child c1;
    }
    int main()
    {
        run();
        while (1);
    }
        输出的结果:
    ia= am parent gouzao
    ia= am Child gouzao
    ia= am Child xigou
    ia= am parent xigou
    
    
    

        可见,子类对象创建的时候,是先自动调用父类的构造函数,执行完毕之后再指定子类的构造函数;虚构函数是先析构子类的构造函数,然后再执行父类的析构函数;同时可以看到,析构函数是构造函数的完全相反地执行。

    继承与组合:

        组合就是自身的成员是其他类的对象,这个就叫组合,那么构造函数和析构函数的执行的顺序,

    class Obj
    {
    public:
        Obj(char *s)
        {
            cout << "obj" << " " << s << endl;
        }
    };
    class Parent : public Obj
    {
    public: // 初始化列表
        Parent(char *s) : Obj(s) 
        {
            cout << "parent" << " " << s << endl;
        }
    };
    class Child : public Parent
    {
    private:
        Obj o1; // 来气其他类的对象
        Obj o2; // 两个对象,那么就是两次
    public:
        Child() : o1("o1"), o2("o2"), Parent("paren from")
        {
            cout << "child" << endl; // 最后才执行自己
        }
    };
    int main()
    {
        Child c1;
        while (1);
    }
    执行结果:
    obj paren from // 先父母的父母
    parent paren from // 接着父母
    obj o1  // 再别人
    obj o2 // 再别人
    child  // 最后自己
    
    
    

       构造函数执行的顺序: 先父母,在别人,最后自己;首先可以看到,child 继承 父母,而父母则是继承 obj,很显然必须是先执行 obj 的打印(构造函数),再执行 parent 的构造函数;接着是别人,child 里面有两个 对象作为自己的成员变量,所以就执行两次 obj 的构造函数;最后才是执行自己的 child 打印

    子类和父类的成员同名的时候:

    (1)子类的成员变量和父类的成员变量同名的时候:

        A、子类依然继承父类同名的成员名

        B、子类中通过作用域分别符 :: 来进行区分是哪一个成员

        C.、同名的成员存储在内存中的不同的位置

    class Parent 
    {
    protected:
        int i;
    public:
    };
    class Child : public Parent
    {
    protected:
        int i;
    public:
        Child(int i)
        {
            Parent::i = i;  // 通过作用域进行指定同名的成员变量
            Child::i = i + 1;
        }
        void pri()
        { // 打印父类和子类的 i 值
            cout << "parent ::i = " << Parent::i << endl;
            cout << "Child ::i = " << Child::i << endl;
            cout << "parent i dizhi" << &(Parent::i) << endl;
            cout << "parent i dizhi" << &(Child::i )<< endl;
        }
    };
    int main()
    {
        Child c1(5);
        c1.pri();
        while (1);
    }

        成功打印出: 5 和 6 ,而且 不同 i 的地址是不一样的,也就是说,i 是存储在不同的内存的位置;通过 类名 + ""(作用域操作符)进行区分;

    (2)子类与父类的函数同名:

    class Parent 
    {
    public:
        void f()
        {
            cout << "f A" << endl;
        }
    };
    class Child : public Parent
    {
    public:
        void f()
        {
            cout << "f B" << endl;
        }
    };
    int main()
    {
        Child c1;
        c1.f();
        while (1);
    }

    while (1);

    }

        输出的结果是: f B,当子类与父类函数名相同的时候,那么子类是没有办法调用父类的同名函数的,因为父类的同名函数被编译器做隐藏的处理,

  • 相关阅读:
    阿里云ECS安全组之新手不得不面对的问题
    【云栖风向标】VOL.3:阿里云:对不起_这个官司我不服!
    Linux全自动安装wdcp面板脚本
    “程序员”和“码农”究竟有什么区别?
    安卓新标准出台_告别乱弹窗_你的手机真会省电么?
    16年程序员平均工资122478元_你拖后腿了没?
    6.5世界环境日!来聊聊那些你想不到的环保黑科技?
    小扎曝Facebook北极数据中心图片_最先进数据中心都建在哪?
    js之单例模式
    js 之 call 、 apply
  • 原文地址:https://www.cnblogs.com/qxj511/p/5217361.html
Copyright © 2020-2023  润新知