zoukankan      html  css  js  c++  java
  • C++笔记------类的继承和多态

    从已有的类派生出新的类,叫继承。派生类继承了基类的特征和方法。
    公有继承:基类的公有成员成为派生类的公有成员;基类的私有成员成为派生类的一部分,但只能通过基类成员方法和保护方法访问。
    派生类构造函数,通过成员初始化列表的方式指明使用的基类构造函数,并传递基类信息。非构造函数不能使用初始化列表语法。

    派生类可以使用基类不是私有的方法。

    class A
    {
    private:
        int num;
    public:
        int a;
    public:
        A():a(10),num(1)
        {}
        void Show_num()
        {
            cout << num <<endl;
        }
        ~A(){}
    };
    class B:public A
    {
    public:
        int b;
        B():A(),b(5){}
        ~B(){}
    };
    
    int main()
    {
        B b1;
        cout << b1.b <<" " << b1.a <<endl;
        b1.Show_num();   //b1只能通过基类公有方法访问私有数据。
    }

    在派生类的对象创建中,首先是虚基类的构造函数,并按照声明顺序构造。然后是非虚基类的构造函数,
    之后是成员对象的构造函数,最后是派生类自己的构造函数。
    派生类对象过期先调用派生类析构函数,然后再调用基类析构函数。

    class D1
    {
    public:
        D1()
        {
            cout << "D1 create" <<endl;
        }
        ~D1()
        {
            cout <<  "D1 free 
    ";
        }
    };
    class D2
    {
    public:
        D2()
        {
            cout << "D2 create" <<endl;
        }
        ~D2()
        {
            cout <<  "D2 free 
    ";
        }
    };
    class D3
    {
    public:
        D3()
        {
            cout << "D3 create" <<endl;
        }
        ~D3()
        {
            cout <<  "D3 free 
    ";
        }
    };
    class D4:public D1,virtual public D2
    {
    public:
        D3 tt;
        D4():tt()
        {
            cout << "D4 create" <<endl;
        }
        ~D4()
        {
            cout <<  "D4 free 
    ";
        }
    };
    int main()
    {
        D4 tt;
        return 0;
    }

    1.子类能给父类赋值(向上转换),但父类不可以给子类赋值

    2.基类的指针可以指向派生类,基类的引用可以引用派生类对象。但只能调用基类的方法。派生类指针和引用不可以指向基类和引用基类。重新定义基类方法将隐藏基类方法。

    派生类可以使用作用域解析符来调用基类方法。

    class D1
    {
    public:
        D1()
        {
            cout << "D1 create" <<endl;
        }
        void show()
        {
            cout << "D1 show"<< endl;
        }

          void show1()
          {
              cout <<" D1 show1() ";
          }

          ~D1()

        {
            cout <<  "D1 free 
    ";
        }
    };
    class D2
    {
    public:
        D2()
        {
            cout << "D2 create" <<endl;
        }
        void show()
        {
            cout << "D2 show" <<endl;
        }
        ~D2()
        {
            cout <<  "D2 free 
    ";
        }
    };
    class D4:public D1,virtual public D2
    {
    public:
        D4():tt()
        {
            cout << "D4 create" <<endl;
        }
        void show()
        {
            cout << "D4 show" <<endl;
        }

          void show1(int i)
         {
              cout << i <<" D4 show1() ";
         }

    ~D4()
        {
            cout <<  "D4 free 
    ";
        }
    };
    int main()
    {
        D4 tt;
        D2 t2;
        D1 t1;
        t1 = tt; 
        //tt = t1;  //报错 
        D2* t3 = &tt;
        D1 & t4=tt; 
        t3->show();      //调用D2的show函数
        t4.show();        //调用D1的show函数
        tt.show();        //调用D1的show函数
        tt.D1::show();  //调用D1的show函数
        //tt.show1();   //报错,显示没有show1()函数
    tt.show1(2);
    return 0; }

    有两种多态性
      1.编译时的多态性,通过函数重载和运算符重载实现。
      2.运行时的多态,程序执行时无法根据函数名和参数确定调用那一个函数,必须根据具体执行情况动态的确定,通过类继承关系和虚函数实现。
    Ps:

    1.函数如果为虚函数则在继承体系中,函数一直默认为虚函数。

    2.派生类中重新定义虚函数时(覆盖),要函数名,参数列表和返回值要与基类相同(三同)

    3.如果返回类型是基类指针,派生类返回派生类指针是可以的。如果不同则重载。

    4.静态成员函数(所有对象共同拥有),内联函数,全局函数(只有类的成员函数才能是虚函数),不能作为虚函数。

    5.构造函数不能定义为虚函数,因为调用构造函数是对象没有完成实例化。

    6.如果函数在类内声明,类外实现。vistual只用在类声明的方法原型中。

    7.使用virtual,程序根据引用或指针的对象选择方法。没有virtual,则根据引用或指针类型调用方法。

    8.将基类的析构函数定义为虚析构函数,为了保护让程序正确调用析构函数。

    9.编译器处理虚函数是为对象添加一个隐藏成员,该成员保存了指向虚函数的地址数组的指针,称为虚函数表。

    重载,隐藏和覆盖

      重载:在同一作用域中,同名,不同参数列表的函数之间是重载。
      隐藏:在父类中的函数没用virtual关键字,子类同名函数会隐藏父类函数,不能使用父类函数
      覆盖:在虚函数表中,子类的虚函数地址覆盖父类同名的虚函数地址

    在多继承中虚函数表
      没有覆盖的情况下,子类的虚函数地址只会添加在第一个父类虚函数表后面,其它父类虚函数表中没有
      在有覆盖的情况下,子类的虚函数地址会覆盖所有父类同名的虚函数地址。

    private与protected区别
      派生类成员可以直接访问基类保护成员,但不能直接访问基类私有成员。
      保护访问控制让派生类能够访问公众不能使用的内部函数。
    纯虚函数

      virtual void show() = 0 ;

    抽象基类(ABC):包含纯虚函数的类(无论有无实现),不能创建对象。

      因为纯虚函数没有实现部分,所以不能产生对象。

      子类如果没有重写ABC的纯虚函数则也不能创建对象,必须把所有纯虚函数重写。

      如果纯虚函数提供实现代码,可以通过类名做限定进行调用ABC的函数实现代码。

    //有一个抽象基类A(已提供实现代码)
    B b;
    b.show();
    b.A::show();
  • 相关阅读:
    LOJ #6008. 「网络流 24 题」餐巾计划
    P2144 [FJOI2007]轮状病毒
    随记
    1010: [HNOI2008]玩具装箱toy(斜率优化)
    HDU 3507 Print Article(斜率优化)
    4819: [Sdoi2017]新生舞会(分数规划)
    POJ 2976 Dropping tests(01分数规划)
    spoj 104 Highways(Matrix-tree定理)
    dp专练
    4152: [AMPPZ2014]The Captain
  • 原文地址:https://www.cnblogs.com/zhangzeze/p/8722448.html
Copyright © 2011-2022 走看看