美文网首页
虚函数 纯虚函数 虚类

虚函数 纯虚函数 虚类

作者: Myth52125 | 来源:发表于2017-08-09 23:08 被阅读0次

    虚函数

    类的某些函数,基类希望它的派生类各自定义这些函数各自的版本。
    除了构造函数,任何函数都可以是虚函数。
    让派生类继承借口和缺省定义(默认定义)。

    定义&声明

    class A
    {
    virtual int get(){};
    };
    
    class B:public A
    {
    int get() override
    }
    

    如果是普通的虚函数(不是纯虚函数),那么基类也是需要提供虚函数的定义的。
    因为不是纯虚函数,那么该类就可以实例化,那就必须需要定义。
    派生类必须在其内部重新定义的虚函数进行声明。

    在基类中定义虚函数的时候需要在最开头加virtual

    虚函数可以有默认实参,且派生类也可以定义不同的默认实参,但是最好相同。

    重写

    在子类函数重写的时候,可以选择加也可以选择不加virtual。同时,如果可以在最结尾的时候加override确认是重写。
    在派生类中覆盖了某个虚函数时,可以再一次使用virtual指出该函数的性质,也可以不加。但一个函数被声明为虚函数时,在他的所有派生类中,都是虚函数。
    重写时,虚函数的返回值,形参必须完全相同。

    但是,当基类返回的是自己类型的指针时。那么气派生类可以修改虚函数的返回值,但必须是返回派生类自身类型的指针。

    另外,在分离定义的时候,不能加virtual.

    关键字

    override

    使用override关键字,用来确认定义的函数确实是覆盖了基类的虚函数,如果没有覆盖,那么编译时候会报错。

    使用

    类的函数成员分类

    1. 普通函数成员:基类希望其派生类直接继承,而不要改变的函数
    2. 虚函数:基类希望其派生类进行覆盖的函数。

    普通虚函数,可以派生类可以不用重写。
    纯虚函数,必须重写。

    普通成员函数,其解析过程发生在编译时。
    虚函数的解析可能在编译时,也可能是在运行时。
    当通过指针或引用调用对象的虚函数时。那么函数会在运行时才会被解析。

    这里解析的含义是,当对象调用自己的成员函数的时候,是执行自己的成员函数,还是执行其子类的成员函数。
    当将一个派生类对象的指针或引用赋值给基类对象指针时(此时会发生派生类向基类的转化),在运行时解析。执行的是派生类的成员函数。

    如果我们想回避虚函数的动态绑定机制,而直接运行派生类基类的成员函数。(调用的函数仍然是一个虚函数,只是我们希望调用基类的)。

    pa->A::set();
    

    显式的指定。那么函数将在编译时完成解析。

    抽象基类

    接口类

    纯虚函数

    纯虚函数的目的是为了让派生类只继承借口,不继承定义。所以必须要定义。

    定义

    class A
    {
    virtual int get()=0;
    };
    

    =0只能在类内出现。
    同时仍然可以在类外提供这个函数的定义。唯一的调用方式是显式调用。
    出纯虚函数可以不提供定义,因为这个类不能够实例化。但是可以定义指向这个类的指针。
    同时这个类里面还是可以出现正常的虚函数,成员变量。

    构造函数

    派生类构造函数只初始化他的直接基类。也就是说派生类在构造函数中只能调用直接基类的构造函数,不能使用其间接基类的构造函数。

    class C:public B
    {
    public:
      C():B(),A()
      {
      };
    }
    

    这里报错

     type 'A' is not a direct base of 'C'
      C():B(),A(){};
    

    虚析构函数

    任何函数,只要带有一个虚函数,那么他的析构函数必将是虚函数。

    如果一个类的析构函数不是虚函数,那么不能将派生类向基类转化

    如果say()函数不是虚函数

    //忽略大部分
    A *pa;
    B *pb;
    pa=pb;
    
    pa->say();
    

    执行的是类A的成员函数。

    如果say()函数是虚函数,那么执行的是 类B的函数成员。

    所以,如果基类的析构函数不是虚函数,那么我们使用上述的转化的时候,析构的将是类A的析构函数。
    那么其派生类部分的成员将无法析构。

    所以,析构函数必须是虚函数。

    析构时,从最外层向基层依次执行析构函数.

    构造函数和析构函数中不能使用虚函数

    构造函数中,构造不完全,调用的是基类的函数.
    同样析构时也一样。

    对象构造期间,虚函数不是虚函数。所以调用不会出错,只是不知道会发生什么。
    也就是说,派生类构造时,如果正处于基类构造函数执行期间,那么类型是基类类型,也就是说谁的构造函数在执行,那类型就是什么。
    因为,如果将基类函数定义为虚函数。那么,无法初始化。编译会报错。

    相关文章

      网友评论

          本文标题:虚函数 纯虚函数 虚类

          本文链接:https://www.haomeiwen.com/subject/gtmxrxtx.html