为什么C++不能有虚构造函数,却可以有虚析构函数

本文介绍了C++中虚函数的工作原理及其在运行时的绑定方式,并详细解释了为何析构函数通常需要声明为虚函数以确保正确的资源清理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

class B{
public :
   virtual void m1();
   virtual void m2();
};
class D : public B{
    virtual void m1();
}

有天参加某大公司笔试,遇到这个问题,回来重新翻看C++教材和网上找答案,才恍然大悟。答案如下:

C++的动态绑定使用vtable(虚成员函数表)来实现。vtable支持运行时查询,使系统可以将某一函数名绑定到vtable的特定入口地址。

例如上段代码的虚函数表为:

虚成员函数       入口地址虚成员函数            入口地址
B::m1              0x7723 D::m1                    0x99a7
B::m2              0x23b4 D::m2                   0x23b4

由于系统执行虚函数时,要从对象的vtable找到函数入口地址,而且vtable是存储于对象的内存空间中。假如对象没有实例化,就找不到vtable。因此,构造函数不能是vittual。


但是,析构函数一般都需要加上virtual,假如定义Base *b = new Deriver; Deriver是Base的子类,并且~Base()不为virtual。那么当对象被注销时,系统只会调用~Base(),而不会调用~Deriver(),因为b是Base类型,已被静态绑定析构函数。如果基类或子类用new创建了内存空间,就必须通过析构函数销毁。因此必须使用vitual析构函数,实现动态绑定。

抽象类是面向对象编程中的一个重要概念,它不能被实例化,只能作为基类被继承。抽象类通常包含一个或多个纯虚函数,这些函数没有实现,必须在派生类中实现。抽象类的特点包括: 1. **不能实例化**:抽象类不能创建对象,只能作为基类被继承。 2. **包含纯虚函数**:至少包含一个纯虚函数,这些函数没有实现,必须在派生类中实现。 3. **提供接口**:抽象类通常用于定义接口,强制派生类实现特定的功能。 4. **支持多态**:通过抽象类可以实现多态性,派生类可以重写基类的虚函数,从而实现不同的行为。 在C++中,构造函数和析构函数可以是虚函数吗? 1. **构造函数不能是虚函数**:C++中构造函数不能是虚函数,因为构造函数在对象创建时调用,而虚函数表在对象创建后才初始化。 2. **析构函数可以是虚函数**:析构函数可以是虚函数,通常建议将基类的析构函数定义为虚函数,以确保在删除派生类对象时能够正确调用派生类的析构函数,防止资源泄漏。 ```cpp class Base { public: virtual ~Base() { std::cout << "Base destructor called" << std::endl; } }; class Derived : public Base { public: ~Derived() { std::cout << "Derived destructor called" << std::endl; } }; int main() { Base* obj = new Derived(); delete obj; // 输出: Derived destructor called 然后输出: Base destructor called return 0; } ``` 在这个例子中,`Base`类的析构函数是虚函数,因此在删除`Derived`类对象时,会先调用`Derived`类的析构函数,然后再调用`Base`类的析构函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值