读书人

关于虚函数和this指针的有关问题

发布时间: 2013-08-10 21:14:06 作者: rapoo

关于虚函数和this指针的问题
// livetest.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

class TaskScheduler
{
public:
TaskScheduler()
{}
~TaskScheduler()
{}
typedef void BackgroundHandlerProc(void* clientData);
public:
void turnOnBackgroundReadHandling(BackgroundHandlerProc* handlerProc, void* clientData)
{
fhandlerProc = handlerProc;
fclientData = clientData;

}
BackgroundHandlerProc* fhandlerProc;
void* fclientData;
void singlestep()
{
(*fhandlerProc)(fclientData);
}
};
TaskScheduler* fTaskScheduler = new TaskScheduler();
class RTSPServer
{
public:
RTSPServer()
{

fTaskScheduler->turnOnBackgroundReadHandling(&incomingRequestHandler,this);
}
~RTSPServer()
{
}
void test()
{
fTaskScheduler->singlestep();
}
public:
static void incomingRequestHandler(void* instance)
{
RTSPServer* server = (RTSPServer*)instance;
server->print();
server->incomingConnectionHandlerRTSP1();
}
void RTSPServer::incomingConnectionHandlerRTSP1()
{
this->print();
}
virtual void print()
{
printf("this is parent \n");
}
};
class DynamicRTSPServer : public RTSPServer
{
public:
DynamicRTSPServer():RTSPServer()
{
}
~DynamicRTSPServer()
{
}
static DynamicRTSPServer* DynamicRTSPServer::createnew()
{
return new DynamicRTSPServer();
}
private:
virtual void print()
{
printf("this is child \n");
}
};

int _tmain(int argc, _TCHAR* argv[])
{
RTSPServer* pa;
pa = DynamicRTSPServer::createnew();
fTaskScheduler->singlestep();
return 0;
}

有两个疑问请教大牛们:
1:turnOnBackgroundReadHandling函数传递的指针是RTSPServer的this 怎么打印信息是“this is child”
2:incomingConnectionHandlerRTSP1()函数中this指的不是RTSPServer吗?
3:将RTSPServer()函数改成
RTSPServer()
{
fTaskScheduler =new TaskScheduler();
fTaskScheduler->turnOnBackgroundReadHandling(&incomingRequestHandler,this);
fTaskScheduler.singlestep();
}
fTaskScheduler是RTSPServer的成员变量结果怎就不一样呢??


先感谢各位大牛 本人菜鸟详细点哈 !!!!


[解决办法]



1 你参数传进去的就是把RTSPServer的指针传给了TaskScheduler指针
2 调用的对象是谁,就是谁的this指针,你调用是 RTSPServe对象,
this 指针就是指 RTSPServe
3 只是在 RTSPServe的构造函数中new一个TaskScheduler一个对象而已,
会调用TaskScheduler的构造函数,有那里不一样呢

[解决办法]
多态,要区分指针的类型、指针指向的对象的类型这2个概念。
this指针: 谁传的就是谁,即使指针的类型改了,指针指向的对象的类型还是没改。
不是虚函数,只看指针类型
虚函数,看指针指向的实际对象的类型。

[解决办法]
引用:
Quote: 引用:

楼主的问题就是动态绑定的问题,虚函数是干什么的,就是来干这样事的

1:turnOnBackgroundReadHandling函数传递的指针是RTSPServer的this 怎么打印信息是“this is child”
虽然传递进去的是RTSPServer指针,但是实例对象确是DynamicRTSPServer对象
就如同 Parent *p = new Child();p->print();一样,运行时动态绑定到Child的print打印出来的当然是Child的信息。
2:incomingConnectionHandlerRTSP1()函数中this指的不是RTSPServer吗?
是,这里的this与incomingConnectionHandlerRTSP()里的server都是当前RTSPServer对象指针,但同时也是可以指向RTSPServer子类对象的,这里就是指向了一个DynamicRTPServer对象
3:将RTSPServer()函数改成
RTSPServer()
{
fTaskScheduler =new TaskScheduler();
fTaskScheduler->turnOnBackgroundReadHandling(&incomingRequestHandler,this);
fTaskScheduler.singlestep();
}
fTaskScheduler是RTSPServer的成员变量结果怎就不一样呢??
这里没有涉及DynamicRTPServer实例的创建,仅仅是基本的RTPServer对象,调用print时当然不会打印子类对象信息


感谢您的回答哈 本人很菜 不好意思哈 还是有点不明白。
我知道RTPServer指针可以指向基类的对象,但是第一个问题中的this指针是怎么指向基类对象的呢 根本没见过他赋值啊。
第二个问题中的this是怎么指向DynamicRTPServer的呢

第三个问题中我在mian函数中也创—ynamicRTPServer实例了啊

在此感谢各位的回答

为了编译楼主理解,笔者对这个例子进行少许修改
去掉TaskScheduler,这是可以毋庸置疑的。TaskScheduler存在的作用就是进行函数名和参数的绑定及调用,这里用到的地方都可以直接使用incomingRequestHandler(this);

修改后的代码1(最初代码的修改版):
//#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

class RTSPServer{


public:
RTSPServer(){
//注意1、之前进行的绑定在新版本不需要做
//fTaskScheduler->turnOnBackgroundReadHandling(&incomingRequestHandler,this);
}
~RTSPServer(){}
//void test(){
//fTaskScheduler->singlestep();
//}
public:
static void incomingRequestHandler(void* instance){
RTSPServer* server = (RTSPServer*)instance;
server->print();
server->incomingConnectionHandlerRTSP1();
}
void RTSPServer::incomingConnectionHandlerRTSP1(){
this->print();
}
virtual void print(){
printf("this is parent \n");
}
};
class DynamicRTSPServer : public RTSPServer{
public:
DynamicRTSPServer():RTSPServer(){}
~DynamicRTSPServer(){}
static DynamicRTSPServer* DynamicRTSPServer::createnew(){
return new DynamicRTSPServer();
}
private:
virtual void print(){
printf("this is child \n");
}
};

int _tmain(int argc, _TCHAR* argv[]){
RTSPServer* pa;
pa = DynamicRTSPServer::createnew();
//注意2、调用修改如下
//fTaskScheduler->singlestep();
pa->incomingRequestHandler((RTSPServer*)pa);

return 0;
}



修改后的代码2(RTSPServer构造方法修改后):
//#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

class RTSPServer{
public:
RTSPServer(){
//注意1、这里既绑定又调用
//fTaskScheduler = new TaskScheduler();
//fTaskScheduler->turnOnBackgroundReadHandling(&incomingRequestHandler,this);
//fTaskScheduler->singlestep();
incomingRequestHandler(this);
}
~RTSPServer(){}
//void test(){
//fTaskScheduler->singlestep();
//}
public:
static void incomingRequestHandler(void* instance){
RTSPServer* server = (RTSPServer*)instance;
server->print();
server->incomingConnectionHandlerRTSP1();
}
void RTSPServer::incomingConnectionHandlerRTSP1(){
this->print();
}
virtual void print(){
printf("this is parent \n");
}
};
class DynamicRTSPServer : public RTSPServer{
public:
DynamicRTSPServer():RTSPServer(){}
~DynamicRTSPServer(){}
static DynamicRTSPServer* DynamicRTSPServer::createnew(){
return new DynamicRTSPServer();
}
private:
virtual void print(){
printf("this is child \n");
}
};

int _tmain(int argc, _TCHAR* argv[]){
RTSPServer* pa;
pa = DynamicRTSPServer::createnew();


//fTaskScheduler->singlestep();//为了比较,这句可以暂且注释

return 0;
}



代码1对于虚方法的调用时在RTSPServer外部,pa->incomingRequestHandler((RTSPServer*)pa);执行时动态绑定了子类的print方法

而代码2而对于虚方法的调用是在RTSPServer内部,这样incomingRequestHandler(this);最终等同于{this->print();this->print();}也就等同于{print();print();}等同于{printf("this is parent \n");printf("this is parent \n");}了

读书人网 >C++

热点推荐