C++多态中的构造函数和析构函数

常见问题

  1. 构造函数可以是虚函数吗?
    答:构造函数不可以是虚函数。
    原因:
    构造对象时必须知道对象的实际类型,但是虚函数调用在运行时才能确定对象的实际类型,这会导致编译器无法确定对象的具体类型。
    虚函数的执行依赖于虚函数表(vtable),虚函数表在构造函数中进行初始化工作,即初始化vptr(指向虚函数表的指针)。在构造对象期间,虚函数表还没有被初始化,因此无法通过虚函数表来调用构造函数。

  2. 析构函数可以是虚函数吗?
    答:作为父类时,析构函数必须是虚函数。
    当通过基类指针删除派生类对象时,基类的析构函数是虚函数时才能正确调用派生类的析构函数,从而避免内存泄漏等问题。

  3. 构造函数和析构函数也不能调用虚函数,前者是因为虚表指针还没有被初始化,后者是因为虚表指针可能已经被析构了。

  4. 虚函数表是在编译期间生成的,虚函数表属于类,类的所有对象共享这个类的虚函数表。虚函数表指针在运行时创建,每个实例对象都有一个虚函数表指针。

代码测试

首先定义两个类:

基类:
class Person
{
public:
    Person()
    {
        qDebug()<<"Person 构造函数";
    }
    ~Person()
    {
        qDebug()<<"Person析构函数";
    }
};

派生类:
class Student: public Person
{
public:
    Student()
    {
        qDebug()<<"Student 构造函数";
    }
    ~Student()
    {
        qDebug()<<"Student 析构函数";
    }
};

输出测试:

    Person *pPerson = new Person;
    delete pPerson;
    pPerson = nullptr;

    qDebug()<<endl;

    Student *pStudent = new Student;
    delete pStudent;
    pStudent = nullptr;

    qDebug()<<endl;

    Person *p = new Student();
    delete p;
    p = nullptr;

输出结果:

删除pPerson时:
Person 构造函数
Person析构函数

删除pStudent时:
Person 构造函数
Student 构造函数
Student 析构函数
Person析构函数

删除p时:
1. 基类的析构函数不是虚函数时:
Person 构造函数
Student 构造函数
Person析构函数

2. 基类的析构函数是虚函数时:
Person 构造函数
Student 构造函数
Student 析构函数
Person析构函数

结果分析

  1. 创建一个类对象指针时,调用构造函数;删除对象指针时,自动调用析构函数。
  2. 创建派生类对象指针时,首先调用基类的构造函数,然后调用派生类的构造函数;删除该对象指针时先调用派生类的析构函数,然后调用基类的析构函数。
  3. 基类指针指向派生类对象时,创建时先调用基类的构造函数,然后调用派生类的构造函数;如果基类的析构函数不是虚函数,那么删除该指针时,只调用基类的析构函数,不调用派生类的析构函数。
  4. 基类指针指向派生类对象时,创建时先调用基类的构造函数,然后调用派生类的构造函数;如果基类的析构函数是虚函数,那么删除该指针时,先调用派生类的析构函数,再调用基类的析构函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

VectorAL

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

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

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

打赏作者

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

抵扣说明:

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

余额充值