c++中的虚函数与纯虚函数

文章目录

虚函数


  1. 由于在类的继承派生过程中,可以在派生类中定义和基类中的相同函数,但由于有时需要声明基类指针或引用去指向派生类对象,由于赋值兼容原则对于派生类中派生定义的成员是不可见的,调用同名函数的时候只能默认调用基类中的定义,而虚函数机制则可以解决这个问题,将同名函数在基类中定义为虚函数后,就可以通过基类指针或引用在调用函数时根据所指对象类型的不同而自动选择调用不同类中的函数,实现运行时的动态绑定,也是一种多态性的体现

  2. 定义格式:

    virtual return_type <function_name> (argument1,argument2,…){…}

  3. 虚函数的声明只能是作为基类的类的成员函数,不能是一般函数、友元函数、全局函数、静态函数(在不作基类的类中声明虚函数没有必要)

  4. 虚函数与函数重载的区别,重载函数的本质还是不同的函数的同名表示,编译器通过实际调用时的参数数量、类型、是否const来判断是哪一个重载,但虚函数机制是父类与子类中完全相同的函数定义实现,即函数名、函数返回值、函数形参数量、函数形参类型必须完全相同,编译器仅通过调用时指针或引用所指向对象所属类来选择该类中的虚函数重写,故虚函数的区别仅在于函数体中的具体实现不同,而重载实际还是不同的函数

  5. 派生类的基类的析构函数尽量定义为虚函数(否则,当声明基类指针或引用去动态分配派生类的对象空间,虽然分配了派生类大小的空间,但由于通过基类指针或引用只能看到属于基类部分的数据,即派生类部分数据始终不可见,而在使用后释放空间时,也只会默认调用基类的析构函数导致派生类部分空间没办法得到释放)

  6. 由于虚函数的实质是通过函数指针的特性,在实际调用的时候通过this指针找到一个叫做vptr(虚指针)的指针去访问一块专门用来存储虚函数地址的空间,从该空间中找到所调用的函数地址返回,从而调用该函数,而该空间是在构造函数中自动分配的,故构造函数不能定义为虚函数,否则将产生矛盾性错误

  7. 子类中定义的虚函数重写的函数头部分必须与父类中虚函数的定义完全相同,若形参类型和数量发生变化,编译器将仅仅将两个函数视为不同类中的同名函数,按同名成员调用原则处理,该函数将被视为派生类中的派生部分成员,即过基类指针或引用将永远无法访该函数,而如果仅仅只是重写为返回值的不同,将会出错(error)

  8. 虚函数一般仅用于子类对于父类的相同函数不同实现的重写,以及通过基类指针或引用对不同派生类的相同函数调用期望得到不同的实现的情况

  9. 虚函数的形参默认值:虚函数的形参默认值只有在基类中给出的有效,在派生类中给出的形参默认值在使用基类指针或引用调用执行时将被忽视

  10. 虚函数也可以通过同名成员访问原则访问到基类中的虚函数,即函数前加上基类的域名限定符

纯虚函数


  1. 同虚函数,纯虚函数也定义在基类中,大部分性质与虚函数一致,不同在于纯虚函数在基类中定义时一般不给出函数体,形参列表后以 ‘= 0;’ 结束,同时定义了纯虚函数的基类称为抽象类类型,其类本身不可以声明实例,即纯虚函数的定义是为了强制其派生类中写出相同函数的定义将其覆盖,即用于使得子类强制继承父类的某些函数属性

  2. 定义格式:

    virtual return_type <function_name> (argument1,argument2,…) = 0;

  3. 虚函数与纯虚函数:虚函数与纯虚函数都可用于向其子类说明需要定义其相同函数的覆盖,但虚函数并不强制,且虚函数所属类可实例化,虚函数本身可被调用,而纯虚函数强制其子类定义其函数的覆盖,否则使用其类声明实例时编译报错(error),且纯虚函数所属类不可被实例化,故以下情况考虑使用纯虚函数定义抽象类类型:

    • 当想在基类中抽象出一个方法,且该基类只做能被继承,而不能被实例化
    • 这个方法必须在派生类(derived class)中被实现
  4. 同虚函数一样,纯虚函数的重写应当与其定义时的头部完全一致,否则会报错(error)

  5. 抽象类中的析构函数一般应当定义为虚函数

  6. 纯虚函数是不能还是不用给出函数体?

    • 不用并非不能,实际上,纯虚函数在 ‘ = 0’后依旧可以给出函数体,但由于一般情况下没必要,故往往不会给出,当基类的纯虚函数给出函数体后,只能通过一种方式调用到该函数,即使用派生类对象的实例,通过同名成员访问原则调用该函数,否则其余方法都只能调用到派生类中对该函数的重写当然,有一种情况例外,即析构函数定义为纯虚函数时,编译器可以自行判断执行对该纯虚析构函数的调用,故如果将析构函数定义为纯虚函数,则必须给出函数体
  7. 纯虚函数的形参默认值:纯虚函数的形参默认值同虚函数一样只有在基类中给出的默认值有效,在派生类中给出的默认值将被忽视

注1:通过基类指针或引用访问派生类成员只有在公有继承下才能达到目的,否则会报错

注2:不可使用抽象类声明对象,但可以声明对象指针和对象引用

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值