昨天我看孙鑫的视频第三课(MFC的来龙去脉),在孙鑫讲到CWinApp的构造函数时,函数内部有个pThreadState->m_pCurrentWinThread= this; 孙鑫强调这里的this是指的子类的对象的指针,还叫我们下来自己做个测试程序。 然后我自己做了个测试程序:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class people
{
public:
people()
{
r=this;
}
void pprint()
{
cout<<"people"<<endl;
}
people *r;
};
class police:public people
{
public:
police()
{
}
void pprint()
{
cout<<"police"<<endl;
}
};
police man;
int _tmain(int argc, _TCHAR* argv[])
{
man.r->pprint();
people *p=new police();
p->pprint();
people pp;
pp.pprint();
return 0;
}
这个程序按理说我觉得应该是显示为:
police
police
people
但是显示结果却是
people
people
people
我就很纳闷了,这到底是什么原因?后来我在people类当中的pprint函数加上了一个virtual,这样一来结果就成第一种结果了!我就在想为什么不加virtual的时候他会都显示people呢,我开先认为是man.r没有指向police对象的指针,后来单步调试的时候发现,man.r的确指向的是一个police对象的指针,那到底又是为什么一个指向police对象的指针调用pprint函数的时候会是调用基类的pprint呢? 我后来上csdn问了这个问题,但是社友们回答的和我想问的完全占不上边,可能是我的表达有误吧! 今天我又通过个调试,我觉得这个问题应该是这样的:
首先说明一点,类当中所有的非静态函数都有一个隐含的形参 那就是 const 类名* this(我这里是const people* this和const police* this),这就不难理解上面那两个类的构造函数了。
people(const people* this)
{
r=this;
}
police(const police* this)
{
}
大家应该知道一个基类的指针允许传递一个派生类对象的指针给它。所有当我们构造police man的时候(const police* this=&man),要先调用基类的构造函数(派生类把当前对象的指针传给基类做隐含形参,即const people* this=&man),所以man.r的确是指向的一个police对象的指针。那为什么man.r->pprint()调用会显示为people呢?我认为应该是由于r是一个people类型的指针,虽然它指向的是一个police对象,但是本身是people对象指针,当调用pprint()的时候他会在当前类(people类)中查找这个函数,当找不到时程序会报错(pprint()不是people的函数)。当找到时,由于r是一个指向police对象的指针,系统会查看它是否是虚函数,不是虚函数的话,系统将直接调用这个函数;如果是虚函数的话,系统会查找police类是否有这个函数,police类如果有这个函数,系统将直接调用police类的函数;police类没有这个函数的话,系统将调用基类people的函数pprint()。这样就能解释了在基类中加上virtual和不加virtual的第一个数据的显示结果!后面两个结果的道理完全和第一个的一样。
我如果说的有错的地方,还请大虾们帮忙指正!