关于c++中虚函数和虚函数表的创建时机问题

以这段代码为例。

#include 

using namespace std;

class Parent
{
public:
	Parent()
	{}

	virtual void func1() {};
	virtual void func2() {};
};

class Child :public Parent
{
public:
	Child()
		:n(0)
		,Parent()

	{
		cout << "Child()" << endl;
	}

	virtual void func1() {};
	void func2() {};
	void func3() {};

private:
	int n;
};

int main()
{
	Child c;
	return 0;
}

1. 虚函数表

虚函数表在编译时创建

编译时,对于包含虚函数的类,编译器会自动先为各个类创建好它们各自的虚函数表,其中对于子类重写父类的虚函数等工作也都完成了。

类的函数(包括虚函数)存储在代码段;

类的虚函数表存储在数据区中。

2. 虚函数表指针_vftptr

虚函数表指针在运行时创建

实例化含虚函数的子类对象时,分以下几步走:

  1. 开辟内存空间
  2. 构造父类
  3. 在类的首地址处,填入编译时创建完毕的虚函数表的地址,即虚函数表指针
  4. 进入类的构造函数,执行初始化列表
  5. 执行构造函数body部分

就如上面那段代码,汇编语言:

关于c++中虚函数和虚函数表的创建时机问题_第1张图片

⭕平时做题时经常遇到,在父类的构造函数中,通过指向子类的父类this指针,调用了虚函数,且子类中重写了该虚函数。但是,此时子类的虚函数表并未明确(虚函数表指针尚未填入),所以不会触发多态,还是会调用父类的虚函数。
关于c++中虚函数和虚函数表的创建时机问题_第2张图片

补充:

初始化列表的初始化顺序与初始化列表顺序无关。

  1. 对于成员变量,按成员变量的声明顺序进行初始化。
  2. 对于父类构造,按继承的声明顺序正向进行构造。

而对于子类调用析构后,自动调用父类的析构,对于多个父类,安装继承的声明顺序反方向进行析构。

#include 

using namespace std;

class Parent
{
public:
	Parent()
	{
		cout << "Parent()" << endl;
	}
	~Parent()
	{
		cout << "~Parent()" << endl;
	}
};

class Base
{
public:
	Base()
	{
		cout << "Base()" << endl;
	}
	~Base()
	{
		cout << "~Base()" << endl;
	}
};

class Child :public Parent, public Base
{
public:
	Child()
		:Base()
		,Parent()
	{
		cout << "Child()" << endl;
	}
	~Child()
	{
		cout << "~Child()" << endl;
	}
};

int main()
{
	Child c;
	return 0;
}

关于c++中虚函数和虚函数表的创建时机问题_第3张图片

你可能感兴趣的:(日常难点记录,c++)