【C++】构造函数、析构函数中的虚函数

  构造函数或者析构函数中有虚函数,那实际执行的是哪个函数,测试代码如下:

#include <iostream>
class A {
public:
	A() {
		printf("*** A() begin ***\n");
		f();
		g();
		printf("*** A() end ***\n\n");
	}
	void g() { printf("A g()\n"); }
	virtual void f() { printf("A f()\n"); }
	virtual ~A()	// 不加 virtual 会只执行父类的析构
	{
		printf("*** ~A() begin ***\n");
		f();
		g();
		printf("*** ~A() end ***\n\n");
	}
};

class B : public A {
public:
	B() {
		printf("*** B() begin ***\n");
		f();
		g();
		printf("*** B() end ***\n\n");
	}
	void g() { printf("B g()\n"); }
	void f() override { printf("B f()\n"); }
	~B() {
		printf("*** ~B() begin ***\n");
		f();
		g();
		printf("*** ~B() end ***\n\n");
	}
};

int main() {
	A* p = new B;

	printf("p->f() -> ");
	p->f();

	printf("p->g() -> ");
	p->g();

	printf("\n");
	delete p;
}

  输出如下:

*** A() begin ***
A f()
A g()
*** A() end ***

*** B() begin ***
B f()
B g()
*** B() end ***

p->f() -> B f()
p->g() -> A g()

// A 中析构函数如果不是虚函数,则没有这一段输出
*** ~B() begin ***
B f()
B g()
*** ~B() end ***
// A 中析构函数如果不是虚函数,则没有这一段输出

*** ~A() begin ***
A f()
A g()
*** ~A() end ***

  从上边的代码和结果可以看出:
  1、构造函数执行顺序是:先父类,后子类;析构函数的执行顺序是:先子类,后父类。
  2、父类的析构函数必须是虚函数,否则 delete 时候不会执行子类析构函数,会内存泄漏。
  3、同名,同参虚函数能正常达到多态效果,不是虚函数就会出现 “隐藏”,父类指针只能调用父类函数,ReSharper提示如下。

  4、类的构造函数和析构函数中,虚函数表现不出多态!
  在VS中,ReSharper 会提示构造函数和析构函数中的虚函数会被 静态处理,也就是用这个类自己的,如下图。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值