单继承与多继承中的虚函数表和虚函数指针

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单继承与多继承中的虚函数表和虚函数指针相关的知识,希望对你有一定的参考价值。

首先,我们了解一下何为单继承,何为多继承??

单继承:一个子类只有一个直接父类。

多继承:一个子类有两个或多个直接父类。

单继承中的虚函数表分析:

示例程序:

#include <iostream>
using namespace std;

typedef void(*FUNC)();

class Base
{
public:
	virtual void func1()
	{
		cout << "Base::func1()" << endl;
	}
	virtual void func2()
	{
		cout << "Base::func2()" << endl;
	}
private:
	int _b;
};

class Derive :public Base
{
public:
	virtual void func1()
	{
		cout << "Derive::func1()" << endl;
	}
	virtual void func3()
	{
		cout << "Derive::func3()" << endl;
	}
	virtual void func4()
	{
		cout << "Derive::func4()" << endl;
	}
private:
	int _d;
};
void PrintVfptr(int* vptr)
	//打印虚函数表
{
	cout << "虚函数表: " << vptr << endl;
	for (int i = 0; vptr[i] != 0; ++i)
	{
		printf("第%d个虚函数:%p  >> ", i, vptr[i]);
		FUNC f = (FUNC)(vptr[i]);
		f();
	}
}

void Test()
{
	Base b;
	Derive d;

	int* vptrBase = (int*)(*(int*)(&b));
	int* vptrDeri = (int*)(*(int*)(&d));

	PrintVfptr(vptrBase);
	cout << endl;
	PrintVfptr(vptrDeri);

}

int main()
{
	Test();
	system("pause");
	return 0;
}

程序运行结果:

Base类(基类)的虚函数表:

技术分享

Derive类(派生类)的虚函数表:

技术分享

结论:

如果有虚函数表,那么只有一个虚函数表,并且按照虚函数声明的顺序顺序排列,派生类的虚函数紧接着基类的虚函数排列


多继承中的虚函数表分析:

示例代码:

#include <iostream>
using namespace std;

typedef void(*FUNC)();
class Base
{
public:
	virtual void func1() = 0;
	virtual void func2() = 0;
};

class Base1:public Base
{
public:
	virtual void func1()
	{
		cout << "Base1::func1()" << endl;
	}
	virtual void func2()
	{
		cout << "Base1::func2()" << endl;
	}
private:
	int _b1;
};

class Base2: public Base
{
public:
	virtual void func1()
	{
		cout << "Base2::func1()" << endl;
	}
	virtual void func2()
	{
		cout << "Base2::func2()" << endl;
	}
private:
	int _b2;
};


class Derive : public Base1, public Base2
{
public:
	virtual void func1()
	{
		cout << "Derive::func1()" << endl;
	}
	virtual void func3()
	{
		cout << "Derive::func3()" << endl;
	}
	virtual void func4()
	{
		cout << "Derive::func4()" << endl;
	}
private:
	int _d;
};

void PrintVfptr(Base* b)
{
	int* vTable1 = (int*)(*(int*)b);
	cout << "虚函数表指针:" << vTable1 << endl;
	for (int i = 0; vTable1[i] != 0; ++i)
	{
		printf("第%d个虚函数指针: %p   >>", i, vTable1[i]);
		FUNC f = (FUNC)vTable1[i];
		f();
	}
	//int* vTable2 = (int*)(*((int*)b + sizeof(Base1) / 4));
	int* vTable2 = (int*)(*((int*)((char*)b + sizeof(Base1))));
	cout << "虚函数表指针:" << vTable2 << endl;
	for (int i = 0; vTable2[i] != 0; ++i)
	{
		printf("第%d个虚函数指针: %p   >>", i, vTable2[i]);
		FUNC f = (FUNC)vTable2[i];
		f();
	}
}

void Test()
{
	Base1 b1;
	Base2 b2;
	Derive d;
	PrintVfptr(&b1);
	cout << endl;
	PrintVfptr(&b2);
	cout << endl;
	PrintVfptr((Base1*)&d);
}

int main()
{
	Test();
	system("pause");
	return 0;
}

程序运行结果:

Base1的虚函数表:

技术分享

Base2的虚函数表:

技术分享

Derive的虚函数表:(有两个虚函数表)

技术分享

多继承中的菱形继承:

示例代码:

#include <iostream>
using namespace std;

typedef void(*FUNC)();
class Base
{
public:
	virtual void func1()
	{
		cout << "Base::func1()" << endl;
	}
	virtual void func2()
	{
		cout << "Base::func2()" << endl;
	}
private:
	int _b;
};

class Parent1 :public Base
{
public:
	virtual void func1()
	{
		cout << "Parent1::func1()" << endl;
	}
	virtual void func3()
	{
		cout << "Parent1::func3()" << endl;
	}
	virtual void func4()
	{
		cout << "Parent1::func4()" << endl;
	}
	virtual void func5()
	{
		cout << "Parent1::func5()" << endl;
	}
private:
	int _p1;
};

class Parent2 :public Base
{
public:
	virtual void func1()
	{
		cout << "Parent2::func1()" << endl;
	}
	virtual void func3()
	{
		cout << "Parent2::func3()" << endl;
	}
	virtual void func6()
	{
		cout << "Parent2::func6()" << endl;
	}	
	virtual void func7()
	{
		cout << "Parent2::func7()" << endl;
	}
private:
	int _p2;
};

class Child :public Parent1, public Parent2
{
public:
	virtual void func1()
	{
		cout << "Child::func1()" << endl;
	}
	virtual void func3()
	{
		cout << "Child::func3()" << endl;
	}
	virtual void func4()
	{
		cout << "Child::func4()" << endl;
	}
	virtual void func6()
	{
		cout << "Child::func6()" << endl;
	}	
	virtual void func8()
	{
		cout << "Child::func8()" << endl;
	}
private:
	int _c;
};

void PrintVfptr(int* vptr)
	//打印虚函数表
{
	cout << "虚函数表: " << vptr << endl;
	for (int i = 0; vptr[i] != 0; ++i)
	{
		printf("第%d个虚函数:%p  >> ", i, vptr[i]);
		FUNC f = (FUNC)(vptr[i]);
		f();
	}
}
void Test()
{
	Base b;

	Parent1 p1; 
	Parent2 p2;

	Child c;

	int* vptr_B = (int*)(*(((int*)(&b))));

	int* vptr_P1 = (int*)(*(((int*)(&p1))));

	int* vptr_P2= (int*)(*(((int*)(&p2))));

	PrintVfptr(vptr_B);
	cout << endl;

	PrintVfptr(vptr_P1);
	cout << endl;

	PrintVfptr(vptr_P2);
	cout << endl;

	int* vptr_C_1 = (int*)(*(((int*)(&c))));
	int* vptr_C_2 = (int*)(*(int*)((char*)(&c) + sizeof(Parent1)));

	PrintVfptr(vptr_C_1);
	cout << endl;
	PrintVfptr(vptr_C_2);
	cout << endl;
}
int main()
{
	Test();
	system("pause");
	return 0;
}

运行结果:

技术分享其中,Child有两个虚函数表,因为它有两个直接父类。


总结:多继承中会有多个虚函数表,几重继承就会有几个虚函数表。这些虚函数表会按照派生的顺序依次排列。如果子类改写了父类的虚函数,那么就会用子类自己的虚函数覆盖相应的父类虚函数;如果子类有新的虚函数,那么就添加到第一个虚函数表的末尾。

以上是关于单继承与多继承中的虚函数表和虚函数指针的主要内容,如果未能解决你的问题,请参考以下文章

虚继承和虚函数继承

基本语言

多态实现之虚函数

C++多态

9-4:C++多态之单继承和多继承中的虚函数表

C++的虚函数表和虚析构