• c++ --> 父类与子类间的继承关系


    父类与子类间的继承关系

     

    一、父类与子类

    父类与子类的相互转换

    1、派生类的对象可以赋给基类,反之不行
    2、基类的指针可以指向派生类,反之不行
    3、基类的引用可以初始化为派生类的对象,反之不行
    4、派生类指针必须强制转换为基类指针后才可以指向基类
    5、基类指针转换为派生类指针容易导致崩溃性错误
    6、虚基类的引用或派生不能转换为派生类
    class father{
      //
    };
    class son : public father{
      //
    };
    int main() { father f; son s; f = s;//正确 s = f;//错误 father *pf = new son;//正确 son *ps = new father;//错误 father &rf = s;//正确 father &rs = f;//错误 return 0; }

    继承关系对基类成员的影响

      公有成员 保护成员 私有成员
    公有继承 公有 保护 不可访问
    保护继承 保护 保护 不可访问
    私有继承 私有 私有 不可访问
    成员函数 1 1 1
    对象 1 0 0
    子类 1 1 0
    1:可以访问 0:不可访问
    当所有成员都变成不可访问时,再往下派生就没有意义了。
     
     
    二、子类的构造与析构
    1、构造派生类对象时,先执行基类的构造函数,再执行子类的构造函数,析构反之
    class father
    {
    public:
        father(){cout<<"father construct"<<endl;}
        ~father(){cout<<"father delete"<<endl;}
    };
    class son : public father
    {
    public:
        son(){cout<<"son construct"<<endl;}
        ~son(){cout<<"son delete"<<endl;}
    };
    int main()
    {
        son s;
        return 0;
    }

    输出:

    father construct
    son construct
    son delete
    father delete

    2.如果是多重继承,基类的构造顺序按给定的顺序,析构反之

    class father
    {
    public:
        father(){cout<<"father construct"<<endl;}
        ~father(){cout<<"father delete"<<endl;}
    };
    class mother
    {
    public:
        mother(){cout<<"mother construct"<<endl;}
        ~mother(){cout<<"mother delete"<<endl;}
    };
    class son : public father, public mother
    {
    public:
        son(){cout<<"son construct"<<endl;}
        ~son(){cout<<"son delete"<<endl;}
    };
    int main()
    {
        son s;
        return 0;
    }

    输出:

    father construct
    mother construct
    son construct
    son delete
    mother delete
    father delete

    3.利用基类的构造函数构造子类,效率更高

    class father
    {
        int x;
    public:
        father(int a):x(a){cout<<"father construct:"<<x<<endl;}
    };
    class son : public father
    {
        int y;
    public:
        son(int a, int b):father(a), y(b){cout<<"son construct:"<<y<<endl;}
    };
    int main()
    {
        son s(1, 2);
        return 0;
    }

    输出:

    father construct:1
    son construct:2

    三、多重继承

    1.多重继续的二义性,根本原因是

    假如A有Test(),则B和C都有Test(),于是D产生了二义性

    class A
    {
    public:
        void Test(){cout<<"A"<<endl;}
    };
    class B
    {
    public:
        void Test(){cout<<"B"<<endl;}
    };
    class C : public A, public B
    {
    };
    int main()
    {
        C c;           
        c.Test();      //错误
        c.A::Test();   //正确,输出:A
        c.B::Test();   //正确,输出:B
        return 0;
    }

    2.编译器通常都是从离自己最近的目录树向上搜索的

    子类的Test()覆盖了基类的Test(),并不代表基类的Test()消失,只是不能直接访问

    class A
    {
    public:
        void Test(){cout<<"A"<<endl;}
    };
    class B
    {
    public:
        void Test(){cout<<"B"<<endl;}
    };
    class C : public A, public B
    {
        void Test(){cout<<"C"<<endl;}
    };
    int main()
    {
        C c;           
        c.Test();      //正确,输出:C
        c.A::Test();   //正确,输出:A
        c.B::Test();   //正确,输出:B
        return 0;
    }
     
    3.对于单一继承,子类能否访问父类的父类,只与继承的方式有关
    对于多重继承,子类不能直接访问父类的父类。
     
    4.用virtual来避免二义性。
    class B : virtual public A.
     
     
    四、继承与包含
    1.一个类的成员变量列表中包含另一个类的对象,叫做包含(包容)。
    2.包含与私有继承的区别:
    包含:
    1)使程序看上去更清晰易懂
    2)不存在继承带来的问题
    3)可以包括另一个类的多个对象
     
    私有继承:
    1)可以访问基类的保护成员
    2)可以重定义虚函数,实现多态
     
     
  • 相关阅读:
    华为lab-rs-v1-2.11_OSPF与ISIS互通
    jdk源码分析红黑树——插入篇
    jdk源码分析PriorityQueue
    jdk源码分析ArrayDeque
    jdk链表笔记
    jdk顺序表笔记
    SpringMVC类型转换器、属性编辑器
    SpringMVC基本使用
    spring整合hibernate
    spring aop注解配置
  • 原文地址:https://www.cnblogs.com/jeakeven/p/4560364.html
Copyright © 2020-2023  润新知