多态虚函数

文章详细介绍了多态的概念,包括静态多态和动态多态,重点讲解了动态多态如何通过虚函数实现。文章讨论了虚函数的特性,如不能在静态成员函数和构造函数中使用,并强调析构函数应为虚函数。还阐述了重载、重写和重定义的区别,并给出了虚函数重写的例子。最后,探讨了虚函数表的作用以及对象大小与虚函数表的关系。


一、多态是什么?

简单来说就是多种状态,去完成某个行为的时候,不同对象就完成时会产生不同的形态,可以分为静态多态动态多态
静态多态是:重载和模板,在编译阶段来实现
动态多态是:可以使用虚函数来实现

动态多态实现条件:
1、必须对虚函数进行重写
2、父类的指针或者引用去调用对象。

1、类里面的成员函数

1、1虚函数

virtual关键字修饰的成员函数,通过指针的指向的对象去调用虚函数,虚函数必须有this指针
几种情况分析如下:

静态成员函数不能是虚函数(因为不存在this指针)
构造函数不能成为虚函数(虚函数指针是在构造函数初始化列表阶段初始化)
析构函数可以是虚函数,且最好把基类的析构函数定义为虚函数(析构函数重写的名字不能一致

示例如下:

class A
{
public:
    virtual ~A()
    {
        cout << "~A()" << endl;
    }
};
class B : public A
{
public:
    virtual ~B()
    {
        cout << "~B()" << endl;
    }
};

实现效果
在这里插入图片描述

1、2三种状态

重载:在同一个作用域中只需要函数名相同,参数不同
重写:两个函数分别在基类和派生类,函数名/参数/返回值必须相同(协变例外),两个函数得是虚函数
重定义:两个函数分别在基类和派生类中,函数名相同,不构成重写就是重定义

三者关系如下所示
在这里插入图片描述

1、3 虚函数的重写

重写的时候派生类被重写的虚函数也可以没virtual修饰

代码如下(示例):

class A
{
public:
    virtual void f()
    {
        cout << "A::f()" << endl;
    }
};
class B : public A
{
public:
    virtual void f()
    {
        cout << "B::f()" << endl;
    }
};

1、4 多态的实现

代码如下(示例):

int main()
{
    A a;
    B b;
    A* ptr1 = &a;
    A* ptr2 = &b;
    ptr1->f();
    ptr2->f();
    return 0;
}

实现结果

在这里插入图片描述

二、虚函数表

这里容易考察一个对象有多大

class A
{
public:
    virtual void f()
    {
        cout << "A::f()" << endl;
    }
public:
    int _a;
};
int main()
{
    A a;
    printf("%d\n", sizeof(a));
}

在这里插入图片描述
(在32位平台下)首先会存在一个虚函数表指针,再加上类成员,共8个字节

虚函数表

是存储虚函数指针的一个数组,在编译阶段就产生,一般情况存储在代码段
在这里插入图片描述
同一类,不同对象公享一张虚表
不同类,各有一张虚表
在这里插入图片描述
在这里插入图片描述
第一个是虚函数指针
第二个是虚函数指针数组的结尾空指针标志

多继承情况下会存在多张虚函数表,并且子类没有重写的虚函数会放在第一个虚函数表末尾

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值