C++虚函数、多态、抽象类和强制类型转换

虚函数

什么是虚函数

类的成员函数前加virtual这种函数就叫虚函数

特点

子类会覆盖父类的虚函数

多态

当子类覆盖了父类的虚函数时,通过父类指针指向子类对象时,调用虚函数,会根据具体的对象是谁来决定执行谁的函数,这就是多态。

多态的条件

1、父子类之间函数有覆盖关系。
2、父类的指针或引用指向子类对象

在构造、析构函数中调用虚函数

1、在父类的构造函数中调用虚函数,此时子类还没有创建完成,因此只能调用父类的虚函数,而不是覆盖版本的虚函数
2、在子类的析构函数中调用虚函数,此时子类已经释放完成,只能调用父类的虚函数,而不是覆盖版本的虚函数。

纯虚函数

在虚函数的声明后面添加=0,这种虚函数就叫纯虚函数,可以不实现,但如果实现必须在类外(只能在父类的构造函数、析构函数中调用)。

virtual 返回值 函数名(参数) = 0;

抽象类

1、成员函数中有纯虚函数,这种类叫抽象类,抽象类不能实例化(不能创建对象)。
2、抽象类必须被继承且纯虚函数被覆盖后,由子类实例化对象。
3、如果继承抽象类,但没有覆盖纯虚函数,那么子类也将称为抽象类,不能实例化。

纯抽象类

1、所有成员函数都是纯虚函数,这种只能被继承的类叫纯抽象类。
2、这种类一般用来设计接口,这种类在子类被替换后不需要被修改,或少量的修改即可继续使用。

虚函数表

什么是虚函数表

在C++的类中,一旦成员函数中有虚函数,这个类中就会多一个虚函数表指针,这个指针指向一个虚函数表,表里记录了这个类中所有的虚函数,当这个类被继承,它的子类也会有一个虚函数表(不管子类中有无虚函数),如果子类的成员函数中有函数签名与父类的虚函数一样的,就会用子类中的函数替换它在虚函数表中的位置,这样就达到了覆盖的效果。
当通过类指针或引用调用函数时,会根据对象中实际的虚函数表记录来调用函数,这样就达到了多态的效果。

虚析构

  • 当使用delete释放一个父类指针时,不管实际指向的对象时子类还是父类都只会调用父类的析构函数。
  • 如果子类的析构函数有需要释放的内存,就会造成内存泄漏。
  • 为了解决这个问题,可以把父类的析构函数设置为虚函数,析构函数进行覆盖时不会比较函数名。
  • 当父类的析构函数为虚函数时,通过父类指针或引用释放子类对象时,会自动调用子类的析构函数,子类的析构函数完成后也会调用父类的析构函数。
    注意:析构函数可以是虚函数,但构造函数不行

强制类型转换

  • 注意:C++中为了兼容C语言,(目标类型)源类型 依然可以继续使用,但C语言中的强制类型转换安全性差,因此建议使用C++中的强制类型转换。
  • 注意:C++之父认为如果代码设计的很完善,根本不需要用到强制类型转换,而C++的强制类型转换之所以设计的很复杂,是为了让程序员多关注代码本身的设计,尽量少使用。
  • C++中的强制类型转换保证没有很大的安全隐患
  • static_cast<目标类型>(源类型) 编译器会对源类型和目标类型做兼容性检查,不通过则报错.
  • dynamic_cast<目标类型>(源类型) 编译器会对源类型和目标类型是否同为指针或引用进行检查,并且存在多态型的继承关系(里面要有虚函数)
  • const_cast<目标类型>(源类型) 编译器会对源类型和目标类型是否同为指针或引用进行检查,除了常属性之外其他必须完全相同否则报错.
  • reinterpret_cast<目标类型>(源类型) 编译器会对源类型和目标类型是否同为指针和整数进行检查,也就是说把整数转换为指针或把指针转换为整数

动态编译和静态编译

静态编译:指针或引用的目标是确定的,在编译时就确定所有类型检查和函数调用.
动态编译:指针或引用的目标是不确定的(多态),只有函数调用时候才确定具体是哪个子类.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值