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

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

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

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

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

示例程序:

#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有两个虚函数表,因为它有两个直接父类。

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

时间: 03-04

单继承与多继承中的虚函数表和虚函数指针的相关文章

C++虚函数表与虚析构函数

1.静态联编和动态联编联编:将源代码中的函数调用解释为要执行函数代码. 静态联编:编译时能确定唯一函数.在C中,每个函数名都能确定唯一的函数代码.在C++中,因为有函数重载,编译器须根据函数名,参数才能确定唯一的函数代码. 动态联编:编译时不能确定调用的函数代码,运行时才能.C++中因为多态的存在,有时编译器不知道用户将选择哪种类型的对象,因此无法确定调用的唯一性,只有在运行时才能确定. 2.虚成员函数,指针或引用,动态联编指针或引用才能展现类的多态性.当类中的方法声明为virtual时,使用指

C++ 虚函数表解析 继承

C++ 虚函数表解析 陈皓 http://blog.csdn.net/haoel 前言 C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有"多种形态",这是一种泛型技术.所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议. 关于虚函数的使用方法,我在这里不做过多的阐述

深入C++对象模型&虚函数表

多态的实现机制: C++中虚函数的主要作用就是用来实现多态,就是使用基类的指针或者引用调用重写的虚函数,当父类的指针或引用指向父类对象时调用的是父类虚函数,当指向子类对象时调用的是子类的虚函数.那么这又是怎么实现的呢??? 这都是通过虚函数表实现的,虚函数表是通过一块连续内存来存储虚函数的地址.这张表解决了虚函数重写(地址进行覆盖)的问题 .在有虚函数的对象实例中都有一张虚函数表,虚函数表就像一张地图,指明了实际调用的虚函数函数. 例: class Base { public:        B

C++虚函数及虚函数表解析

一.背景知识(一些基本概念) 虚函数(Virtual Function):在基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数.纯虚函数(Pure Virtual Function):基类中没有实现体的虚函数称为纯虚函数(有纯虚函数的基类称为虚基类).C++  “虚函数”的存在是为了实现面向对象中的“多态”,即父类类别的指针(或者引用)指向其子类的实例,然后通过父类的指针(或者引用)调用实际子类的成员函数.通过动态赋值,实现调用不同的子类的成员函数(动态绑定).正是因为这种

C++之虚函数表

本文引自:http://songlee24.github.io/blog/2014/09/02/c-plus-plus-jin-jie-zhi-xu-han-shu-biao/ C++通过继承(inheritance)和虚函数(virtual function)来实现多态性.所谓多态,简单地说就是,将基类的指针或引用绑定到子类的实例,然后通过基类的指针或引用调用实际子类的成员函数(虚函数).本文将介绍单继承.多重继承下虚函数的实现机制. 一.虚函数表 为了支持虚函数机制,编译器为每一个拥有虚函数

C++ 虚函数表解析

转自陈浩的博客 前言 C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有"多种形态",这是一种泛型技术.所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议. 关于虚函数的使用方法,我在这里不做过多的阐述.大家可以看看相关的C++的书籍.在这篇文章中,我只想从虚函数的实现

C++ 虚函数表解析(转)

转自:http://blog.csdn.net/haoel 前言 C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有"多种形态",这是一种泛型技术.所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议. 关于虚函数的使用方法,我在这里不做过多的阐述.大家可以看看相关的C

C++之:虚函数表

一.文章来由 虚函数表究竟存放在哪里? 二.概念 C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有"多种形态",这是一种泛型技术.所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议. 对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚

c++ 虚函数表

转自 http://blog.csdn.net/haoel/article/details/1948051/ C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有"多种形态",这是一种泛型技术.所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议. 关于虚函数的使用方法,