现在的位置: 首页 > 综合 > 正文

对虚函数的理解

2013年04月28日 ⁄ 综合 ⁄ 共 1646字 ⁄ 字号 评论关闭

情况一:B继承A,有同名函数,基类中的函数不为虚函数

#include <iostream>
using namespace std;

class A
{
public:
	A()
	{  a = 1;b = 2;	}
	~A()
	{}
	void fun()
	{    
		printf("%d %d\n",a,b);
		cout<<"A fun;"<<endl;
	}
	int a;
	int b;
};

class B: public A
{
public:
	B()
	{  c = 3;}
	~B()
	{}
	void fun()
	{    
		printf("%d\n",c);
		cout<<"B fun;"<<endl;
	}
	int c;
};


int _tmain(int argc, _TCHAR* argv[])
{
	A oba;
	B *pb = (B*)(&oba);
	pb->fun();

	B obj;
	A *pa = (A*)(&obj);
	pa->fun();

	system("pause");
	return 0;
}


输出结果:

在没有virtual的情况下,虚函数表中没有相应函数,则直接调用当前类型的相应函数,只是指向的地址有变化。

printf("%d\n",c);这句话输出的结果不定,是因为只调用了A的构造函数,没有调用B的构造函数,从而c没有初值的原因。

而printf("%d %d\n",a,b);是因为在创建B对象obj的时候调用了A、B的构造函数,使得a,b,c都有了初值,所以能正确输出结果~~~

情况二:B继承A,有同名函数,基类中的函数为虚函数

// 11.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

class A
{
public:
	A()
	{  a = 1;b = 2;	}
	~A()
	{}
	virtual void fun()
	{    
		printf("%d %d\n",a,b);
		cout<<"A fun;"<<endl;
	}
	int a;
	int b;
};

class B: public A
{
public:
	B()
	{  c = 3;}
	~B()
	{}
	void fun()
	{    
		printf("%d\n",c);
		cout<<"B fun;"<<endl;
	}
	int c;
};


int _tmain(int argc, _TCHAR* argv[])
{
	A oba;
	B *pb = (B*)(&oba);
	pb->fun();

	B obj;
	A *pa = (A*)(&obj);
	pa->fun();

	system("pause");
	return 0;
}

输出结果:
在有virtual的情况下:
基类的对象实例是不存在虚函数表覆盖的,所以在查询函数时会查询到基类的函数。
派生类的对象实例的虚函数表中的函数会覆盖其中的同名函数,故会查询到派生类函数(也就是多态)。

B *pb是个指针,所以这并没有生产对象,只是分配了一个指向B类对象的指针。

B obj;
A *pa = (A*)(&obj);
pa->fun();

虚表指针是依附于对象存在的这里只构造了B的对象obj,这句表达式只是一个模型转换,不涉及到A类对象的构造,所以pa指向的空间类的虚表指针依然是B类的虚表指针,指向的自然是B类的虚函数。

情况三:B不继承A,有同名函数

#include "stdafx.h"
#include <iostream>
using namespace std;

class A
{
public:
	A()
	{  a = 1;b = 2;	}
	~A()
	{}
    void fun()
	{    
		printf("%d %d\n",a,b);
		cout<<"A fun;"<<endl;
	}
	int a;
	int b;
};

class B
{
public:
	B()
	{  c = 3;}
	~B()
	{}
	void fun()
	{    
		printf("%d\n",c);
		cout<<"B fun;"<<endl;
	}
	int c;
};


int _tmain(int argc, _TCHAR* argv[])
{
	A oba;
	B *pb = (B*)(&oba);
	pb->fun();

	B obj;
	A *pa = (A*)(&obj);
	pa->fun();

	system("pause");
	return 0;
}

输出结果:

这种情况只是单纯的指针指向的地址不同而已~

抱歉!评论已关闭.