C++ Virtual Function One

virtual function

The role of virtual functions

A very important concept in object-oriented programming is polymorphism, which refers to
Makes a base class pointer to a derived class object, and when a function common to both base and derived classes is called, the function of the derived class is finally called.
as follows

class Base{
public:
	virtual void f(){
		cout<<"Base call f()";
	}
}; 

class Derived : public Base{
public:
	virtual void f(){
		cout<<"Derived call f()";
	}
};
int main(){
	Base* pb = new Derived();
	pb->f();
}

The final results are as follows

Implementation principle of virtual function

The reason for this is that if a virtual function is defined in a class, a virtual function table pointer is generated when an object is generated, which points to the virtual function table, where there is a pointer to the virtual function defined in the class.

With these virtual functions, we can call virtual functions.

When a derived class inherits a base class, it also generates a virtual function table in which there are parent classes and self-defined virtual methods. If the virtual method of the base class is overridden, the original virtual function method of its base class is overridden in the virtual function table by the method overridden by the derived class.

Verification of Virtual Function Implementation Principle

Verify first
If a virtual function is defined in the class, a virtual function table pointer is generated when the object is generated

class A{
public:
	A(){cout<<"call A()"<<endl;}
	~A(){cout<<"call A()"<<endl;}
};
class B{
public:
	B(){cout<<"call B()"<<endl;}
	
	virtual void virtualBB(){cout<<"call virtualBB()"<<endl;}
	virtual void virtualB(){cout<<"call virtualB()"<<endl;}
	virtual ~B(){cout<<"call ~B()"<<endl;}
	
};
int main(){
A a;
	B b;
	cout<<"sizeof(a) = "<<sizeof(a)<<endl;//it should be one size
	cout<<"sizeof(b) = "<<sizeof(b)<<endl;//it should be eight size, a virtual pointer size
}

Revalidation
When a derived class inherits a base class, it also generates a virtual function table in which there is a parent class and a virtual method defined by itself

//author: Solitude
//date: 2021-09-29
//purpose: validate the concept of virtual 

#include <iostream>
using namespace std;

class Base{
public:
	virtual void f(){
		cout<<"Base call f()"<<endl;
	}
}; 

class Derived : public Base{
public:
	virtual void f(){
		cout<<"Derived call f()"<<endl;
	}
};

//validate the concept 
typedef void (*PF)();
class A{
public:
	A(){cout<<"call A()"<<endl;}
	~A(){cout<<"call A()"<<endl;}
};
class B{
public:
	B(){cout<<"call B()"<<endl;}
	
	virtual void virtualBB(){cout<<"call virtualBB()"<<endl;}
	virtual void virtualB(){cout<<"call virtualB()"<<endl;}
	virtual ~B(){cout<<"call ~B()"<<endl;}
	
};

int main(){
	#if 0
	Base* pb = new Derived();
	pb->f();
	#endif
	
	#if 1
	A a;
	B b;
	cout<<"sizeof(a) = "<<sizeof(a)<<endl;//it should be one size
	cout<<"sizeof(b) = "<<sizeof(b)<<endl;//it should be eight size, a virtual pointer size
	PF pf;
	pf =  (PF)*((int*)*(int*)(&b)+0);
	pf();
	pf =  (PF)*((int*)*(int*)(&b)+2);
	pf();
	#endif
	return 0;
}

give the result as follows
typedef void (PF)();Acts as a function pointer that is defined to call the virtual function pointed to by the virtual function pointer in the virtual function table.
(PF) ((int*) (int) (&b) +0); usage is somewhat ambiguous, let me explain
Let's break it down step by step

(int*)(&b)
(&b) is the address of the virtual function pointer, and we convert it to an int* type pointer so that we get a pointer to the virtual function table.

(int*)(int)(&b)
To further complicate the problem, (int)(&b) gives us the position of the first virtual function pointer in the virtual function table, and we convert it to an int* type pointer, which gives us a pointer to the virtual function.

(PF)((int)(int)(&b)+0)
A little more complicated,
((int) (int) (&b) +0) gives us the position of the first virtual function pointed to in the virtual function table, which we then use (PF) to convert into a function pointer. This gives us the function pointer for the function virtualBB().
Period plus 0, plus 2 is used to refer to pointer addition, the purpose is to find our virtual function in the virtual function table.

coolshell Chen Hao

Tags: C++

Posted on Wed, 29 Sep 2021 12:09:03 -0400 by zohab