MFC里面this指针问题!请高手帮忙!

lixang000 2008-06-16 08:54:27
引子:
建立一新工程My:
以下是MFC原代码:

CWinApp::CWinApp(LPCTSTR lpszAppName)
{
if (lpszAppName != NULL)
m_pszAppName = _tcsdup(lpszAppName);
else
m_pszAppName = NULL;

// initialize CWinThread state
AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
ASSERT(AfxGetThread() == NULL);
pThreadState->m_pCurrentWinThread = this;

//孙鑫老师说这个This指的是(MyApp theApp);
[color=#FF0000]既this 指的基类的派生出来的MyApp对象;[/color]
。。。。。
}

所以我做了验证:

//A.h
#ifndef _A_H_
#define _A_H_

using namespace std;
class CWinThread {
public: CWinThread(CWinThread*pThread=0 ){ m_pThread=this;};
void Run() { cout<<"CWinThread::Run()"<<endl;}
CWinThread* GetThread(){return this;}
private:
CWinThread* m_pThread;
};

class CWinApp:public CWinThread {
public: CWinApp(){};
void Run() { cout<<"CWinApp::Run()"<<endl;}
};

class MyApp:public CWinApp {
public: MyApp(){};
void Run() { cout<<"Mycpp::Run()"<<endl;}
};

extern MyApp theApp;

//A.cpp
#include<iostream>
#include"a.h"

MyApp theApp;

int main()
{
CWinApp* pApp=&theApp;
pApp->GetThread()->Run();//结果cout<<"CWinThread::Run()"<<endl;
//说明this并不是指MyApp theApp;
}
请高手指点!

...全文
1280 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
dlmult 2011-05-26
  • 打赏
  • 举报
回复
我觉得楼主不是在虔诚的请教,而是在炫耀自己的测试,你的测试例子确实不错,而我们确实虔诚的回答。
iwong 2008-06-17
  • 打赏
  • 举报
回复
this写在哪个类里面,就是指向哪个类,并不是恒指向某个固定的类的。这样说明白否?

class A
{
public:
virtual A* getA()
{
//这里返回A类型的指针
return this;
}
};

class B
{
public:
B* getA()
{
//这里返回B类型的指针
return this;
}
};
zzhprogram 2008-06-17
  • 打赏
  • 举报
回复
哎,楼主啊,不知道你到底是想学习探讨还是要干嘛。
把你的验证程序改一下。你自己对比下,看你自己到底有没有错,错在哪

//A.h
#ifndef _A_H_
#define _A_H_

using namespace std;
class CWinThread
{
public:
CWinThread(CWinThread *pThread=0 ){ m_pThread=this;};
virtual void Run() { cout <<"CWinThread::Run()" <<endl;}
CWinThread* GetThread(){return this;}
private:
CWinThread* m_pThread;
};

class CWinApp:public CWinThread {
public: CWinApp(){};
void Run() { cout <<"CWinApp::Run()" <<endl;}
};

class MyApp:public CWinApp {
public: MyApp(){};
void Run() { cout <<"Mycpp::Run()" <<endl;}
};

MyApp theApp;

#endif


//A.cpp
#include <iostream>
#include"a.h"

extern MyApp theApp;

int main()
{
CWinApp* pApp=&theApp;
pApp->GetThread()->Run();//结果cout < <"CWinThread::Run()" < <endl;
//说明this并不是指MyApp theApp;
return 0;
}


最后一句:态度决定一切
胡椒爸爸 2008-06-17
  • 打赏
  • 举报
回复
建议LZ可以看一下Inside The C++ Object Model和一些其他的相关书籍
胡椒爸爸 2008-06-17
  • 打赏
  • 举报
回复
pApp->GetThread()返回的是 CWinThread*,也就是说这个返回值是的静态类型是一个CWinThread *类型,
当你用这样的一个对象指针去调用成员函数时,会有两种方式选择函数
(1)如果函数是虚函数,则这个时候会展现多态,根据动态类型找到正确的Run函数
(2)如果函数不是虚函数,则根据指针的静态类型查找相关类的函数

这里你的Run函数不是虚函数,所以编译器就是用了静态类型来找到CWinThread类中的Run函数
但是this实际上还是MyApp的指针,你可以直接打印出this的值和theApp变量的地址来看看是不是一样的
Eleven 2008-06-17
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 blh 的回复:]
pApp->GetThread()->Run();//结果cout < <"CWinThread::Run()" < <endl;
GetThread()返回的是CWinThread*,当然结果是CWinThread::Run()
你把这些run()定义成虚函数就是Mycpp::Run()
[/Quote]
stephenxu111 2008-06-17
  • 打赏
  • 举报
回复
this指向本实例,不管这实例是父类还是子类。所以不管你把这个this指针怎么转换,它的值(指向的地址)是不变的,所以"指的基类的派生出来的MyApp对象"的说法是没有问题的。只不过你把它转换成继承树上的其他类的指针,再调用该指针对应的方法,由于该方法已被继承下来,所以这并不能说明什么。

this是指向实例的指针,而不是指向类的指针。你的例子中实例只有一个,this的类型被转换,但指向的对象可没有变。
lixang000 2008-06-17
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 fflush 的回复:]
C/C++ codeclassA
{public:voidfunc () { cout<<"A"; }virtualvoidvfunc () { cout<<"A"; }
};classB :publicA
{public:voidfunc () { cout<<"B"; }virtualvoidvfunc () { cout<<"B"; }
};intmain ()
{
B b;
A*pA=&b;

pA->func ();//输出ApA->vfunc ();//输出Breturn0;
}
上面的例子lz如果看不明白,那么你应该去补习一下c++,而不是在这学MFC,如果能看明白,你能说pA指向的一个A对象,而不是一个B对象吗,如…
[/Quote]

我看不明白你举这个例子与我的问题偏差十万八千里!

你没看到我在顶层红字专门强调(非虚函数):
因为我真的使用了虚拟函数对我的命题只有混淆问题的作用,故此我专门使用了三个非虚函数!
这更利于我很好的演示那个this究竟是指向了派生类还是它自己本身!

你还是把我的问题仔细看以下回复,而不是急着说话,到头来给后面的帮助着者少添些乱!
如果this真的指的是MyApp对象则会输出cout < <"CMyApp::Run()" < <endl;
blh 2008-06-17
  • 打赏
  • 举报
回复
pApp->GetThread()->Run();//结果cout < <"CWinThread::Run()" < <endl;
GetThread()返回的是CWinThread*,当然结果是CWinThread::Run()
你把这些run()定义成虚函数就是Mycpp::Run()
hai040 2008-06-17
  • 打赏
  • 举报
回复
(MyApp*)(pApp->GetThread())->Run();

Run不是虚函数,结果跟前面指针的类型相关

楼上已经有人说了,this的数值没变
int i;
char* p = &i;
p指向的是不是i?
fflush 2008-06-17
  • 打赏
  • 举报
回复

class A
{
public:
void func () { cout << "A"; }
virtual void vfunc () { cout << "A"; }
};

class B : public A
{
public:
void func () { cout << "B"; }
virtual void vfunc () { cout << "B"; }
};

int main ()
{
B b;
A * pA = &b;

pA->func (); // 输出A
pA->vfunc (); // 输出B

return 0;
}

上面的例子lz如果看不明白,那么你应该去补习一下c++,而不是在这学MFC,如果能看明白,你能说pA指向的一个A对象,而不是一个B对象吗,如果你依旧这么认为,那么你应该去补习一下逻辑学,而不是在这学MFC
lixang000 2008-06-17
  • 打赏
  • 举报
回复
楼上的zzhprogram,coverallwangp朋友,希望你们把我的问题看明白了再回复,别连问题都没仔细看就急于回
复!

lixang000 2008-06-17
  • 打赏
  • 举报
回复
hqin6:

你的分析有问题:
按照你的说法:
pApp指向的动态类型是MyApp,但是静态类型确实是CWinApp,
那么输出的决不应当是
pApp->GetThread()->Run();//结果cout < <"CWinThread::Run()" < <endl;
你还是好好想想吧!

算了干脆我再把问题抽象出来吧!
就是说
CWinApp::CWinApp(LPCTSTR lpszAppName)
{。。。。。。。
pThreadState->m_pCurrentWinThread = this; //既this 指的基类的派生出来的MyApp对象
}
class CWinApp:public CWinThread {。。。。。};

class MyApp:public CWinApp {。。。。。。};

extern MyApp theApp;//全局变量

我在最上面给出的例子没能演示成功,希望高手能加以演示成功:
要演示的是把指向派生类的this指针在基类中传递给基类的某个成员指针!


太乙 2008-06-17
  • 打赏
  • 举报
回复
晕~~我试试,看能不能给你说明白:

extern MyApp theApp;

//A.cpp
#include <iostream>
#include"a.h"

MyApp theApp;

int main()
{
CWinApp* pApp=&theApp;
pApp->GetThread()->Run();//结果cout < <"CWinThread::Run()" < <endl;
//说明this并不是指MyApp theApp;
}

对于你上面这个程序段,我认为,因为这是继承,没有虚函数的参与,那么由于这个pApp是CWinApp*的类型,所以,计算机看待他是CWinApp的指针,而这里牵扯到俩个概念,就是静态类型和动态类型:静态类型是计算机编译阶段能确定的,动态类型就是在运行时确定的。像我们说的虚函数机制,就是用 的动态类型,虚函数,必须在运行时,根据指针指向的真正类型来确定他该调用哪个函数!

就这个程序来说,pApp的静态类型是CWinApp的,所以,编译器在编译的时候,就把这个GetThread()编译成了CWinApp类里那个GetThread函数的地址,所以运行的时候,当然是那个结果咯


楼主不信,可以写个程序,反汇编试试!


pApp指向的动态类型是MyApp,但是静态类型确实是CWinApp,楼主不信可以写个虚函数试试!

coverallwangp 2008-06-17
  • 打赏
  • 举报
回复
指针只能调用本身类型的函数(虚函数除外),
CWinApp* pApp=&theApp;
pApp->GetThread()->Run();
所以pApp->GetThread()返回的this指针当然就是CWinApp*,在用调用Run()函数,所以输出"CWinThread::Run()"

你可以这样写:
CWinApp* pApp=&theApp;
(static_cast<MyApp*>( pApp->GetThread()))->Run();
这样就调用MyApp的Run()了
lixang000 2008-06-17
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 tangshuiling 的回复:]
楼主这种证明有点差强人意啦,

MyApp theApp; 定义了一个全局的变量在堆栈上开辟了空间,暂设为0x0012ff80;
撇开this不看,0x0012ff80这个没有改变,只是栈中的内容会因为楼主的强转发生类型的变化,对象的类型决定对象的操作,zai(始终应该记住的一点是,栈中的值也没有改变,只是类型发生了强转)。由此,this的值并没有改变,与孙鑫老师所说并无冲突!

[/Quote]

你的说法很难理解!就算我强转发生类型也是由MyApp转为CWinApp并非CWinThread!
还是期待高手指点!

tangshuiling 2008-06-16
  • 打赏
  • 举报
回复
楼主这种证明有点差强人意啦,

MyApp theApp; 定义了一个全局的变量在堆栈上开辟了空间,暂设为0x0012ff80;
撇开this不看,0x0012ff80这个没有改变,只是栈中的内容会因为楼主的强转发生类型的变化,对象的类型决定对象的操作,zai(始终应该记住的一点是,栈中的值也没有改变,只是类型发生了强转)。由此,this的值并没有改变,与孙鑫老师所说并无冲突!
lixang000 2008-06-16
  • 打赏
  • 举报
回复
期待高手指点
lixang000 2008-06-16
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 stephenxu111 的回复:]
为什么说明this并不是指MyApp theApp; ?
pApp->GetThread()得到的是CWinThread的指针,通过CWinThread的指针显示调用Run(),自然输出的是CWinThread::Run(),你又没有使用虚函数。
[/Quote]


这正好证明pApp->GetThread()得到的是CWinThread的指针不是MyApp对象指针

zzhprogram 2008-06-16
  • 打赏
  • 举报
回复
MyApp theApp;

int main()
{
CWinApp* pApp=&theApp;
pApp->GetThread()->Run();//结果cout < <"CWinThread::Run()" < <endl;
//说明this并不是指MyApp theApp;
}
请高手指点!

兄弟你这程序有问题呢,theApp表示程序唯一实例,它自己会调用基类的线程启动函数,你这里怎么又搞出个main?MFC程序是不用自己写main的。pThreadState->m_pCurrentWinThread = this; 这个this就是表示当前程序的实例
加载更多回复(3)

64,646

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧