C++中虚函数是怎样实现的

C++中的多态就是依据虚函数实现的,那么下面借用一个例子来说一下虚函数是怎样实现多态的,并解释一下虚函数到底是怎样实现的。

class ClassA
{
public:
	void fun1();
	void fun2();
	virtual void fun3();
};

void ClassA::fun1()
{
	cout<<"ClassA.fun1"<<endl;
};

void ClassA::fun2()
{
	cout<< "ClassA.fun2"<<endl;
};

void ClassA::fun3()
{
	cout<< "ClassA.fun3"<<endl;
};


class ClassB : public ClassA
{
public:
	void fun1();
	void fun2();
	virtual void fun3();
};

void ClassB::fun3()
{
	cout<< "ClassB.fun3"<<endl;
};

class ClassC : public ClassB
{
public:
	void fun1();
	void fun2();
	virtual void fun3();
};

void ClassC::fun3()
{
	cout<< "ClassC.fun3"<<endl;
};

void main()
{
	ClassA *a[3];
	ClassA a1;
	ClassB b1;
	ClassC c1;


	a1.fun3();
	b1.fun3();
	c1.fun3();

	a[0] = &a1;
	a[1] = &b1;
	a[2] = &c1;
	cout << "virtual function array test" <<endl;
	for(int i=0;i<3;i++)
	{
		a[i]->fun3();
	}

	cout << "((ClassA)&b1).fun3():";
	((ClassA*)&b1)->fun3();
	//object slicing
	cout << "object slicing"<<endl;
	cout <<"((ClassA)b1).fun3():"; 
	((ClassA)b1).fun3();
}

这三个类之间的继承关系是:ClassC继承ClassB,ClassB继承ClaaA,fun3是虚函数,并且在ClassB和ClassC中被重写。

    下面先介绍一下什么是虚函数:在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数。用法格式为:virtual 函数返回类型 函数名(参数表) {函数体};

多态性的实现是通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数

接下来说一下虚函数是怎样实现多态的以及虚函数的实现机制:实际上,编译器是通过一个虚函数表,在运行时间接的调用实际上绑定的函数来达到动态绑定的,这张表对我们来说是透明的,是编译器针对那些包含虚函数的代码自动加上去的。该表每一行的元素是一个指向代码中虚函数的指针,有了这个地址,我们可以调用实际代码中的虚函数了。编译器又通过增加一个指向该虚函数表的指针(vptr)将该表与我们的代码联系到一起。

ClassA中vptr与虚函数表之间的关系图(盗的图)


每一个ClassA的实例,都会有一个虚函数表vptr,当我们在代码中通过这个实例来调用虚拟函数时,都是通过vptr先找到虚拟函数表,接着

虚函数表中再找出指向的某个真正的虚拟函数地址。虚拟函数表中的内容就是类中按顺序声明的虚拟函数组织起来的。在派生的时候,子类都会继承父类的虚拟函数表vptr,若子类改写了父类中的虚拟函数,则子类的vptr成员也会作修改,此时,子类的vptr成员指向的是子类所改写父类的 虚拟函数地址。多态也就体现在这里。 ClassB中vptr与虚函数表之间的关系图

ClassC中的关系也同理。

那么,一个指向ClassA的对象的实例,调用fun3就是ClassA::fun3(),一个指向ClassB的对象的实例,调用fun3就是ClassB::fun3(),一个指向ClassC的对象的实例,调用fun3就是ClassC::fun3(),这些调用通过都是通过虚函数表来进行的。

上面的结果是:

ClassA.fun3
ClassB.fun3
ClassC.fun3
virtual function array test
ClassA.fun3
ClassB.fun3
ClassC.fun3
((ClassA)&b1).fun3():ClassB.fun3
object slicing
((ClassA)b1).fun3():ClassA.fun3
请按任意键继续. . .



                
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值