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

bomengwutao 2013-08-04 10:20:15
// 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的成员变量结果怎就不一样呢??

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

...全文
252 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhctj159 2013-08-04
  • 打赏
  • 举报
回复
楼主的问题就是动态绑定的问题,虚函数是干什么的,就是来干这样事的 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时当然不会打印子类对象信息
bomengwutao 2013-08-04
  • 打赏
  • 举报
回复
引用 5 楼 ananluowei 的回复:
多态,要区分指针的类型、指针指向的对象的类型这2个概念。 this指针: 谁传的就是谁,即使指针的类型改了,指针指向的对象的类型还是没改。 不是虚函数,只看指针类型 虚函数,看指针指向的实际对象的类型。
恩恩 是这个意思啊 但是我的这个测试例子就不对了啊 turnOnBackgroundReadHandling函数传递的指针是RTSPServer的this 他应该调用RTSPServer的print函数啊 怎么调用的是派生类的呢
大尾巴猫 2013-08-04
  • 打赏
  • 举报
回复
多态,要区分指针的类型、指针指向的对象的类型这2个概念。 this指针: 谁传的就是谁,即使指针的类型改了,指针指向的对象的类型还是没改。 不是虚函数,只看指针类型 虚函数,看指针指向的实际对象的类型。
bomengwutao 2013-08-04
  • 打赏
  • 举报
回复
引用 3 楼 max_min_ 的回复:
[quote=引用 2 楼 bomengwutao 的回复:] [quote=引用 1 楼 max_min_ 的回复:]


1  你参数传进去的就是把RTSPServer的指针传给了TaskScheduler指针
2  调用的对象是谁,就是谁的this指针,你调用是 RTSPServe对象,
    this 指针就是指 RTSPServe
3  只是在 RTSPServe的构造函数中new一个TaskScheduler一个对象而已,
   会调用TaskScheduler的构造函数,有那里不一样呢
1: 我传递的是RTSPServer指针可是运行的时候打印的是“this is child”,不是应该打印出“this is parent吗?” 2:this 是RTSPServe 但是打印的是“this is child” 3:按我说的改 你会发现这个两个程序运行结果不一样[/quote]

virtual void print()
        {
            printf("this is parent \n");
        }
因为你父类中写的是虚函数, 你自己类中有继承,所以会调用的子类中的print函数 去掉virtual 你运行看看, 这是回答 1 , 对于2 还是一样, 谁的对象就是谁的this指针,通过上面的问题,这个也就解释了 [/quote] 非常感谢大哥的回答哈 。就是对这个虚函数有疑问 class a { public: a() { this->print(); } ~a() {} virtual void print() { printf("this is parent \n"); } }; class b : public a { public: b() : a() {} ~b() {} virtual void print() { printf("this is chlid \n"); } }; void main() { b pb; } 您看着个代码 执行的就是“this is parent” 因为这个this 指针是父类的 所以即使他是虚函数调用的而是自己的a中的函数 和上面的比较 就有问题了
max_min_ 2013-08-04
  • 打赏
  • 举报
回复
引用 2 楼 bomengwutao 的回复:
[quote=引用 1 楼 max_min_ 的回复:]


1  你参数传进去的就是把RTSPServer的指针传给了TaskScheduler指针
2  调用的对象是谁,就是谁的this指针,你调用是 RTSPServe对象,
    this 指针就是指 RTSPServe
3  只是在 RTSPServe的构造函数中new一个TaskScheduler一个对象而已,
   会调用TaskScheduler的构造函数,有那里不一样呢
1: 我传递的是RTSPServer指针可是运行的时候打印的是“this is child”,不是应该打印出“this is parent吗?” 2:this 是RTSPServe 但是打印的是“this is child” 3:按我说的改 你会发现这个两个程序运行结果不一样[/quote]

virtual void print()
        {
            printf("this is parent \n");
        }
因为你父类中写的是虚函数, 你自己类中有继承,所以会调用的子类中的print函数 去掉virtual 你运行看看, 这是回答 1 , 对于2 还是一样, 谁的对象就是谁的this指针,通过上面的问题,这个也就解释了
bomengwutao 2013-08-04
  • 打赏
  • 举报
回复
引用 1 楼 max_min_ 的回复:


1  你参数传进去的就是把RTSPServer的指针传给了TaskScheduler指针
2  调用的对象是谁,就是谁的this指针,你调用是 RTSPServe对象,
    this 指针就是指 RTSPServe
3  只是在 RTSPServe的构造函数中new一个TaskScheduler一个对象而已,
   会调用TaskScheduler的构造函数,有那里不一样呢
1: 我传递的是RTSPServer指针可是运行的时候打印的是“this is child”,不是应该打印出“this is parent吗?” 2:this 是RTSPServe 但是打印的是“this is child” 3:按我说的改 你会发现这个两个程序运行结果不一样
max_min_ 2013-08-04
  • 打赏
  • 举报
回复


1  你参数传进去的就是把RTSPServer的指针传给了TaskScheduler指针
2  调用的对象是谁,就是谁的this指针,你调用是 RTSPServe对象,
    this 指针就是指 RTSPServe
3  只是在 RTSPServe的构造函数中new一个TaskScheduler一个对象而已,
   会调用TaskScheduler的构造函数,有那里不一样呢
bomengwutao 2013-08-04
  • 打赏
  • 举报
回复
引用 12 楼 zhctj159 的回复:
[quote=引用 8 楼 bomengwutao 的回复:] [quote=引用 7 楼 zhctj159 的回复:] 楼主的问题就是动态绑定的问题,虚函数是干什么的,就是来干这样事的 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函数中也创建DynamicRTPServer实例了啊 在此感谢各位的回答 [/quote] 为了编译楼主理解,笔者对这个例子进行少许修改 去掉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");}了[/quote] 感谢各位的帮助特别是zhctj159哥们,您的回答启发了我 其实这就是this指针的用法问题 当创建DynamicRTSPServer的时候首先调用RTSPServer的构造函数,并将pa的首地址赋值给RTSPServer的this指针。此时的this指针指向pa;当RTSPServer的构造函数结束 再调用DynamicRTSPServer的构造函数,这时pa的内存已经全部初始化完成! 也就是说RTSPServer和DynamicRTSPServer的this指针都是指向pa对象,这样当调用函数的时候自然调用的是 基类的函数了。 这样就不难理解第3个问题了 RTSPServer() { fTaskScheduler =new TaskScheduler(); fTaskScheduler->turnOnBackgroundReadHandling(&incomingRequestHandler,this); fTaskScheduler.singlestep(); } 改成这样 打印的都是“this is parent” 因为RTSPServer()函数还没有结束,DynamicRTSPServer的构造函数还没有调用,this指针的地址还没有包括DynamicRTSPServer的内容,这样执行的都是父类的指针。 哈哈 满意结贴!!!! 再次感谢zhctj159和楼上的各位!找了半天的。基础知识还很不扎实啊
zhctj159 2013-08-04
  • 打赏
  • 举报
回复
引用 8 楼 bomengwutao 的回复:
[quote=引用 7 楼 zhctj159 的回复:] 楼主的问题就是动态绑定的问题,虚函数是干什么的,就是来干这样事的 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函数中也创建DynamicRTPServer实例了啊 在此感谢各位的回答 [/quote] 为了编译楼主理解,笔者对这个例子进行少许修改 去掉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");}了
wuliwu12345 2013-08-04
  • 打赏
  • 举报
回复
这不是很类似吗? class a { public: a(){ printf("class a this is %x\n",this); } void test() { this->print(); } virtual print() { cout<<"class a print"<<endl; } }; class b :public a { public: b(){ printf("class b this is %x\n",this); } void test() { this->print(); } virtual print() { cout<<"class b print"<<endl; } }; int main() { b *ss =new b; ss->test(); return 0; }
bomengwutao 2013-08-04
  • 打赏
  • 举报
回复
求解释哦
bomengwutao 2013-08-04
  • 打赏
  • 举报
回复
up下 没人回答了哦 找资料 真心搞不明白
bomengwutao 2013-08-04
  • 打赏
  • 举报
回复
引用 7 楼 zhctj159 的回复:
楼主的问题就是动态绑定的问题,虚函数是干什么的,就是来干这样事的 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函数中也创建DynamicRTPServer实例了啊 在此感谢各位的回答

64,691

社区成员

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

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