对C++ 虚函数的理解

今天下午看一个开源项目的源码时候,碰到了虚函数。为此,就去查资料了解一下C++虚函数实现机制。

先上代码,对着代码讲。

#include <iostream>
#include <stdio.h>

using namespace std;

class Animal
{
public:
	virtual void eat();   // eat 指定为虚函数 
	virtual void sleep();
	void work();   // work为非虚函数 
	void run();
};

class Dog: public Animal
{
public:
	void eat();
	void work();
};

void Animal::eat()
{
	cout << "Aminal eats something" << endl;
}

void Animal::sleep()
{
	cout << "Animal is sleeping" << endl;
}
void Animal::work()
{
	cout << "Animal works hardly" << endl;
}

void Animal::run()
{
	cout << "Aminal is running" << endl;
}

void Dog::eat()
{
	cout << "Dog eats bone" << endl;
}

void Dog::work()
{
	cout << "Dog works hardly" << endl;
}

int main()
{
	Animal* ani = new Dog();
	ani -> eat();
	ani -> sleep();
	ani -> work();
	
	return 0;
}

程序中定义两个类:基类Animal和派生类Dog,也即是父类Animal和子类Dog。

该程序的函数被分为四类:

1.eat函数是虚函数,被重新定义

2.sleep函数是虚函数,未被重新定义

3.work函数是普通函数,被重写

4.run函数是普通函数,未被被重写。

编译器处理虚函数的方法是,对每个类添加一个隐藏成员:一个虚函数表(virtual function table, vtbl)。这里将会创建两个虚函数表。虚函数表里面存放的是每个类中虚函数的地址,注意这里,只存放虚函数的地址,不会存放其他成员函数。

程序会使用Dog类型的虚拟地址表,所以,这里,eat函数会执行子类的eat函数,而sleep仍然会执行父类的sleep函数。而work函数会执行指针的类型,也就是Animal类型。

也就是,对于父类指针指向子类对象的情况来说,除了被重新定义的虚函数(eat函数)会执行子类的函数(子类eat函数)之外,其他所有类型的函数都将执行父类函数。

执行结果如下:

Dog eats bone
Animal is sleeping
Animal works hardly
Aminal is running

--------------------------------
Process exited after 0.2431 seconds with return value 0
请按任意键继续. . .

那如果想执行子类Dog的work函数怎么办?

强制类型转换!

将main函数改写如下:

int main()
{
	Animal* ani = new Dog();
	ani -> eat();
	ani -> sleep();
	ani -> work();
	ani -> run();
	
	cout << endl;
	
	((Dog*) ani) -> eat();
	((Dog*) ani) -> sleep();
	((Dog*) ani) -> work();
        ((Dog*) ani) -> run();
	
	return 0;
}

执行结果如下:

Dog eats bone
Animal is sleeping
Animal works hardly
Aminal is running

Dog eats bone
Animal is sleeping
Dog works hardly
Aminal is running

--------------------------------
Process exited after 0.1338 seconds with return value 0
请按任意键继续. . .

这时候,就和普通的继承一摸一样了,哦不是,一模(mu)一样。

参考:

1. C++ Prime Plus 第六版(中文版)

2.JAVA的多态用几句话能直观的解释一下吗? - 程序狗的回答 - 知乎 https://www.zhihu.com/question/30082151/answer/120520568

猜你喜欢

转载自blog.csdn.net/tuijiangmeng87/article/details/83096147