虚函数的特点、实现机制以及vTable、vPointer的使用

虚函数能够实现动态联编,是多态的实现形式之一,相同的函数根据对象的不同可以实现不同的功能。本文重点阐述虚函数的实现、注意事项、实现机制。

虚函数的实现

头文件:

#include <iostream>
#include <string>
class BaseClass
{
private:
	std::string base_string_;
public:
	BaseClass(std::string str="BaseClass") :base_string_(str) {}
	virtual void VirtualShow1() const { std::cout << "BaseClass::VirtualShow1 is called and type is " << base_string_ << std::endl; }
	virtual void OverloadShow2() const{ std::cout << "BaseClass::OverloadShow2 is called and type is " << base_string_ << std::endl; }
	void FunctionShow3() const { std::cout << "BaseClass::FunctionShow3 is called and type is " << base_string_ << std::endl; }
	virtual ~BaseClass(){}
};

class DeriveClass :public BaseClass
{
private:
	std::string derive_string_;
public:
	DeriveClass(std::string str1="BaseClass", std::string  str2="DeriveClass") :BaseClass(str1), derive_string_(str2){}
	void VirtualShow1() const { std::cout << "DeriveClass::VirtualShow1 is called and type is " << derive_string_ << std::endl; }
	void OverloadShow2(std::string str) const { std::cout << "DeriveClass::OverloadShow1 is called and " << str << std::endl; }
	void FunctionShow3() const { std::cout << "DeriveClass::FunctionShow3 is called and type is " << derive_string_ << std::endl; }
	virtual ~DeriveClass(){}

};

main.cpp

#include "stdafx.h"
#include "virtualfunction.h"

int _tmain(int argc, _TCHAR* argv[])
{
	BaseClass base_object;
	DeriveClass derive_object;
	BaseClass * point_derive = &derive_object;
	std::cout << "base_object" << std::endl;
	base_object.VirtualShow1();
	base_object.OverloadShow2();
	base_object.FunctionShow3();
	std::cout << "derive_object" << std::endl;
	derive_object.VirtualShow1();
	derive_object.OverloadShow2("this is overload function!");
	derive_object.FunctionShow3();
	std::cout << "point_derive" << std::endl;
	point_derive->VirtualShow1();
	point_derive->OverloadShow2();
	point_derive->FunctionShow3();
	return 0;
}

运算结果:


结果分析:基类对象base_object调用基类的函数,子类对象derive_object调用子类的函数。

当使用基类指针指向子类对象时,即指针point_derive,利用该指针调用重载函数或普通函数时,属于静态联编,根据指针类型来编译,即调用基类函数;利用该指针调用虚函数时,属于动态联编,根据指针指向内容来编译,即调用子类函数

1 基类中使用关键字virtual声明函数为虚函数;

2 继承类中,针对同样的函数,可定义不同的功能(注意:请与函数重载区分开)。在此可用virtual 再次声明,以表明该函数为虚函数,也可省去virtual关键字。当基类声明为虚函数时,继承类的同名函数默认为虚函数;

3 使用基类的指针或引用指向继承类或基类对象,在编译时,会根据对象内容调用函数。

虚函数的注意事项

1 虚函数必须处于基类的public部分,这样才能被对象访问;

2 虚函数不能为静态函数,不能为友元函数;

3 借助指针或引用,利用虚函数可达到动态联编功通过;

4 虚函数的声明原型中,基类与子类的函数名、形参类型、返回类型应相同(需与函数重载分开);

5 构造函数不能为虚函数,析构函数强烈建议为虚函数。

虚函数的实现机制

首先需要了解两个名词:vTable、vPointer

vTable 属于类所有,当该类含虚函数时,编译器会为该类创建vTable表,用于记录该类中所有虚函数的入口地址。

vPointer属于对象所有。使用含有vTable的类创建对象时,编译器自动创建成员函数vPointer,指向vTable表。同一个类的所有对象共用一个vTable表

当调用虚函数时,进行以下4步:

Step1 获取对象的vPointer内容;

Step2 利用vPointer找到vTable;

Step3 利用vTable找到对应的函数入咒骂

Step4 执行对应的虚函数

本文参考以下内容:

参考资料1

参考资料2

发布了12 篇原创文章 · 获赞 14 · 访问量 4655

猜你喜欢

转载自blog.csdn.net/cheetahzhang/article/details/80223197