Analysis of the realization principle of polymorphism ---- virtual table

Three points to achieve polymorphism:
1. There must be at least two classes, and they must be inherited
2. The function must be a virtual function (same name, same parameters, same return type)
3. Implemented through the pointer or reference of the base class


No matter how many virtual functions there are in a class, there will only be one virtual table pointer __vfptr, occupying four bytes

There are two parts in the virtual table: 1. the address of the virtual function; 2. the virtual function;

And the address of the virtual function always ends with 0x00000000.

#include<iostream>
using namespace std;

class Base
{
	virtual void f()
	{}
	virtual void g()
	{}
	virtual void h()
	{}
};

void main()
{
	Derive d;
}


By calling the memory we can clearly see



The following is a detailed understanding of the virtual table from four situations:

1. In the case of single inheritance without coverage, the virtual table of the subclass will follow the virtual table of the parent class (the virtual functions are placed in the table in the order of declaration).

#include<iostream>
using namespace std;

class Base
{
	virtual void f()
	{}
	virtual void g()
	{}
	virtual void h()
	{}
};
class Derive : public Base
{
	virtual void f1()
	{}
	virtual void g1()
	{}
	virtual void h1()
	{}
};

void main()
{
	Derive d;
}

2. In the case of single inheritance with coverage, the overridden subclass will replace the position of the original parent class virtual table, and the rest of the subclass virtual table will follow the parent class.

class Base
{
	virtual void f()
	{}
	virtual void g()
	{}
	virtual void h()
	{}
};
class Derive : public Base
{
	virtual void f()
	{}
	virtual void g1()
	{}
	virtual void h1()
	{}
};

void main()
{
	Derive d;
}

3. In the case of multiple inheritance without coverage, the virtual table of the subclass will follow the virtual table of the first parent class, and the virtual table of the subclass will not appear in other parent virtual tables.

#include<iostream>
using namespace std;

class Base
{
	virtual void f()
	{}
	virtual void g()
	{}
	virtual void h()
	{}
};
class Base1
{
	virtual void f()
	{}
	virtual void g()
	{}
	virtual void h()
	{}
};
class Base2
{
	virtual void f()
	{}
	virtual void g()
	{}
	virtual void h()
	{}
};
class Derive : public Base, public Base1, public Base2
{
	virtual void f1()
	{}
	virtual void g1()
	{}
	virtual void h1()
	{}
};

void main()
{
	Derive d;
}

4. In the case of multiple inheritance and coverage, the overridden subclass will replace the position of all virtual functions of the same name of the parent class in the virtual table, and the rest of the subclass virtual tables will follow the virtual table of the first parent class.

#include<iostream>
using namespace std;

class Base
{
	virtual void f()
	{}
	virtual void g()
	{}
	virtual void h()
	{}
};
class Base1
{
	virtual void f()
	{}
	virtual void g()
	{}
	virtual void h()
	{}
};
class Base2
{
	virtual void f()
	{}
	virtual void g()
	{}
	virtual void h()
	{}
};
class Derive : public Base, public Base1, public Base2
{
	virtual void f()
	{}
	virtual void g1()
	{}
	virtual void h1()
	{}
};

void main()
{
	Derive d;
}

The pointer and reference of the base class mobilize the virtual function of the derived class, not to access the virtual function of the derived class, but to access the virtual function in the base class that is overridden by the derived class.


Therefore, the location of access is still in the base class, and does not enter the derived class, which is also the essence of polymorphism.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325687842&siteId=291194637