About the creation timing of virtual function and virtual function table in c++

Take this code as an example.

#include <iostream>

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. Virtual function table

Virtual function tables are created at compile time

When compiling, for classes that contain virtual functions, the compiler will automatically create their own virtual function tables for each class first , and the work of rewriting the virtual functions of the parent class for subclasses is also completed.

Class functions (including virtual functions) are stored in the code segment;

The virtual function table of the class is stored in the data area.

2. Virtual function table pointer _vftptr

Virtual function table pointers are created at runtime

When instantiating a subclass object with virtual functions, the steps are as follows:

  1. Open up memory space
  2. Construct parent class
  3. At the first address of the class, fill in the address of the virtual function table created during compilation, that is, the virtual function table pointer
  4. Enter the constructor of the class and execute the initialization list
  5. Execute the body part of the constructor

Just like the code above, assembly language:

insert image description here

⭕I often encounter it when doing questions. In the constructor of the parent class, the virtual function is called through the this pointer of the parent class pointing to the subclass, and the virtual function is rewritten in the subclass. However, at this time, the virtual function table of the subclass is not clear (the virtual function table pointer has not been filled), so polymorphism will not be triggered, and the virtual function of the parent class will still be called.
insert image description here

Replenish:

The initialization order of the initialization list is independent of the initialization list order.

  1. For member variables, initialization is performed in the order in which the member variables are declared.
  2. For superclass construction, construction proceeds forward in inherited declaration order.

After the subclass calls the destructor, the destructor of the parent class is automatically called. For multiple parent classes, the declaration order of installation inheritance is destructed in the opposite direction .

#include <iostream>

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

insert image description here

Guess you like

Origin blog.csdn.net/C0631xjn_/article/details/132000143