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;
	return 0;
}

  输出如下:

*** 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、TX的面试题:就是类的构造函数和析构函数中,虚函数表现不出多态!
  在VS中,ReSharper 会提示构造函数和析构函数中的虚函数会被 静态处理,也就是用这个类自己的,如下图。

猜你喜欢

转载自blog.csdn.net/Bob__yuan/article/details/88670364