通过基类的指针或引用调用虚函数构成多态

面向对象三大特征:封装 继承 多态

在C++多态的实现是利用虚函数完成的,派生类对基类的虚函数重写,通过基类的指针或引用调用虚函数来实现多态的特性。本问重点讨论为什么必须是通过基类的指针或引用调用虚函数才能构成多态?我们将按照如下顺序逐步分析:

1.什么是虚函数?

在继承关系中,对基类的成员函数使用virtual关键字修饰后,该成员函数称为虚函数。继承该基类的派生类可以通过对虚函数重写实现多态。当然,派生类对基类的虚函数重写不是必须的。

2.动态绑定和静态绑定

动态绑定:在程序运行时才能确定对象的具体类型,一般只有指针或者引用类型才能进行动态绑定。

静态绑定:在编译时就确定了对象的具体类型,例如内置类型或普通的类类型都是静态绑定。

3.继承关系之间的转换

将派生类类型型转换为基类类型

派生类对象中包含基类部分,这意味着可以像使用基类对象一样在派生类上进行操作。因为派生类对象也包含了基类对象,因此存在从派生类型引用到基类类型的转换,指针也是类似的。一般而言,编译器没有将派生类对象转换为基类对象的自动转换,但是可以使用派生类对象给基类对象进行初始化或赋值。

引用转换不同于对象转换

从派生类对象的指针或引用转换为基类对象的指针或引用和对象转换之间的关系是微妙的。将派生类对象的引用转换为基类对象的引用,派生类对象本身并没有发生变化,而且这之间也不存在临时复制和新的独享,只是将基类对象绑定到派生类对象的基类部分,指针也是如此;将派生类对象传给形参为基类对象的函数时,形参的类型是固定的,永远都是基类类型,即将派生类对象的基类部分复制到基类对象中。

用派生类对象对基类对象进行初始化或赋值

利用派生类对象对基类对象进行初始化或赋值时实际上调用基类的复制构造或赋值操作符,将派生类中的基类部分复制到基类对象中。

从派生类到基类的转换是安全的,这种转换有时也称“从下向上的转换”。

将基类类型转换为派生类类型

基类对象的指针或引用不能直接转换为派生类的指针或引用,如果支持这样的转换就可能导致程序访问不属于自己的内存。同时基类对象也不能自动转换为派生类对象。

基类对象、基类对象的指针或引用可以通过强制类型转换转换成派生类对象或派生类对象的指针或引用。

思考:将基类类型转换为派生类类型不安全为什么还要支持通过强制类型转换将基类类型转换为派生类类型?

当基类对象绑定的是派生类对象时也不能自动将基类对象转换成派生类对象,因为编译器无法知道该对象的实际类型。但实际上这种转换是安全的,在这些情况下,如果知道从基类到派生类的转换是安全的,就可以使用static_cast强制编译器进行转换,或者,可以用 dynamic_cast申请在运行时进行检查。

4.为什么必须是通过基类的指针或引用调用虚函数才能构成多态?

只有通过指针或引用才能进行动态绑定,进而在运行时确定对象的实际类型;同时,从下向上的转换是安全的,所以必须通过基类的指针或引用调用虚函数才能构成多态。

5.覆盖虚函数机制

在继承关系中,有些情况下需要基类完成公共的任务,而派生类来实现自己的任务时就可以将该函数定义成虚函数,在派生类中对虚函数进行重写。但是,如果该派生类也需要完成公共的任务,就可以通过使用作用域操作符指定需要调用的虚函数。示例如下:

#include<iostream>
using namespace std;

class Base
{
public:
    virtual void test(){}
}

class Dervie:public Base
{
public:
    virtual void test(){}
}

void test1(const Base* b)
{
    b->test();//调用Dervie的test函数
    b->Base::test();//调用Base的test函数
}

 

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯狂嘚程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值