构造函数与析构函数能否为虚函数?

探讨C++中构造函数为何不能为虚函数,而析构函数常为虚函数的原因。涉及对象构建过程及vtable调用机制,解析虚构造函数误解。

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

C + + C++ C++:构造函数和析构函数能否为虚函数?

简单回答是:构造函数不能为虚函数,而析构函数可以且常常是虚函数。

1.构造函数不能为虚函数

让我们来看看大牛 C + + C++ C++之父 B j a r n e Bjarne Bjarne S t r o u s t r u p Stroustrup Stroustrup 在《 T h e The The C + + C++ C++ P r o g r a m m i n g Programming Programming L a n g u a g e Language Language》里是怎么说的:

T o To To c o n s t r u c t construct construct a n an an o b j e c t object object, a a a c o n s t r u c t o r constructor constructor n e e d s needs needs t h e the the e x a c t exact exact t y p e type type o f of of t h e the the o b j e c t object object i t it it i s is is t o to to c r e a t e create create. C o n s e q u e n t l y Consequently Consequently, a a a c o n s t r u c t o r constructor constructor c a n n o t cannot cannot b e be be v i r t u a l virtual virtual. F u r t h e r m o r e Furthermore Furthermore, a a a c o n s t r u c t o r constructor constructor i s is is n o t not not q u i t e quite quite a n an an o r d i n a r y ordinary ordinary f u n c t i o n function function, I n In In p a r t i c u l a r particular particular, i t it it i n t e r a c t s interacts interacts w i t h with with m e m o r y memory memory m a n a g e m e n t management management i n in in w a y s ways ways o r d i n a r y ordinary ordinary m e m b e r member member f u n c t i o n s functions functions d o n ′ t don't dont. C o n s e q u e n t l y Consequently Consequently, y o u you you c a n n o t cannot cannot h a v e have have a a a p o n t e r ponter ponter t o to to a a a c o n s t r u c t o r . constructor. constructor.

F r o m From From T h e The The C + + C++ C++ P r o g a m m i n g Progamming Progamming L a n g u a g e Language Language 15.6.2 15.6.2 15.6.2

翻译:普通函数要构造一个对象,构造函数需要它要创建的对象的确切类型。因此,构造函数不能是虚函数。此外,构造函数并不是一个很普通的函数,特别是它与内存管理的交互方式与普通成员函数不同,因此,你不能拥有一个构造函数的桥接器。

然而大牛就是大牛,这段话对一般人来说太难理解了。那下面就试着解释一下为什么:

这就要涉及到 C + + C++ C++对象的构造问题了, C + + C++ C++对象在三个地方构建:

  • 函数堆栈
  • 自由存储区,或称之为堆
  • 静态存储区

无论在那里构建,其过程都是两步:首先,分配一块内存;其次,调用构造函数。好,问题来了,如果构造函数是虚函数,那么就需要通过 v t a b l e vtable vtable 来调用,但此时面对一块 r a w raw raw m e m e o r y memeory memeory(原始内存),到哪里去找 v t a b l e vtable vtable 呢?毕竟, v t a b l e vtable vtable 是在构造函数中才初始化的啊,而不是在其之前。因此构造函数不能为虚函数。

2.析构函数可以是虚函数,且常常如此

这个就好理解了,因为此时 v t a b l e vtable vtable 已经初始化了;况且我们通常通过基类的指针来销毁对象,如果析构函数不为虚的话,就不能正确识别对象类型,从而不能正确销毁对象。

困惑我们的是我们却经常看到“虚构造函数”这样的说法,这就要归咎于不负责任或者说误人子弟的媒体了(包括书、技术文章等等)。因为他们说的是类似下面这样的做法:

class Expr {
public:
     Expr();
     Expr(const Expr&);
     virtual Expr* new_expr() { return new Expr(); }
     virtual Expr* clone() { return new Expr(*this); }
};

参考:C++:构造函数和析构函数能否为虚函数
更多解读:
为什么C++的构造函数不可以是虚函数,而析构函数可以是虚函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值