VC6中,为什么只有类中的static成员函数,才可以做为线程启动函数(ThreadProc)? |
类中的static成员函数,存放在堆区吧? 类中的非静态成员函数,也存放在堆区吧?
如果是,那么为什么会出现如题的现象呢?
|
|
|
回复内容 |
【an_bachelor】: 个人以为应该都放在代码段
【haoranisme】: 堆区就存在代码段吧?
那么,为什么只有类中的static成员函数,才可以做为线程启动函数(ThreadProc)呢?
【laolaoliu2002】: static是c++中很常用的修饰符,它被用来控制变量的存储方式和可见性,下面我将从static修饰符的产生原因、作用谈起,全面分析static修饰符的实质。
static的两大作用:
一、控制存储方式:
static被引入以告知编译器,将变量存储在程序的静态存储区而非栈上空间。
1、引出原因:函数内部定义的变量,在程序执行到它的定义处时,编译器为它在栈上分配空间,大家知道,函数在栈上分配的空间在此函数执行结束时会释放掉,这样就产生了一个问题:如果想将函数中此变量的值保存至下一次调用时,如何实现? 最容易想到的方法是定义一个全局的变量,但定义为一个全局变量有许多缺点,最明显的缺点是破坏了此变量的访问范围(使得在此函数中定义的变量,不仅仅受此函数控制)。
2、解决方案:因此c++中引入了static,用它来修饰变量,它能够指示编译器将此变量在程序的静态存储区分配空间保存,这样即实现了目的,又使得此变量的存取范围不变。
二、控制可见性与连接类型:
static还有一个作用,它会把变量的可见范围限制在编译单元中,使它成为一个内部连接,这时,它的反义词为”extern”.
static作用分析总结:static总是使得变量或对象的存储形式变成静态存储,连接方式变成内部连接,对于局部变量(已经是内部连接了),它仅改变其存储方式;对于全局变量(已经是静态存储了),它仅改变其连接类型。
类中的static成员:
一、出现原因及作用:
1、需要在一个类的各个对象间交互,即需要一个数据对象为整个类而非某个对象服务。
2、同时又力求不破坏类的封装性,即要求此成员隐藏在类的内部,对外不可见。
类的static成员满足了上述的要求,因为它具有如下特征:有独立的存储区,属于整个类。
二、注意:
1、对于静态的数据成员,连接器会保证它拥有一个单一的外部定义。静态数据成员按定义出现的先后顺序依次初始化,注意静态成员嵌套时,要保证所嵌套的成员已经初始化了。消除时的顺序是初始化的反顺序。
2、类的静态成员函数是属于整个类而非类的对象,所以它没有this指针,这就导致了它仅能访问类的静态数据和静态成员函数。
【laolaoliu2002】: 将成员函数声明为静态虽然可以解决作为线程函数的问题,但是它带来了新的问题,那就是static成员函数只能访问static成员。解决此问题的一种途径是可以在调用类静态成员函数(线程函数)时将this指针作为参数传入,并在改线程函数中用强制类型转换将this转换成指向该类的指针,通过该指针访问非静态成员。
【haoranisme】: 学习了,但还是想知道:
为什么只有类中的static成员函数,才可以做为线程启动函数(ThreadProc), 而类的非静态成员函数不可以?
【gaooo】: 成员函数调用需this
【gaooo】: 非成员函数不需要this指针
【haoranisme】: 突然想到,会不会是为了区分代码段和数据段呢?
【robinwjb】: 线程函数是独立于类的实例而存在的,他的生命期不是类的生命期,而是整个process。 试想一下,如果可以用非静态成员函数作为线程函数,如果没有定义一个这个类的实例, 岂不是无法调用线程函数了?
【haoranisme】: 试想一下,如果可以用非静态成员函数作为线程函数,如果没有定义一个这个类的实例, 岂不是无法调用线程函数了?
++++++++++++++++++++++++++++++++++++++++++++++++++++ 不明白呀!
【LiChenYue】: 学习!关注!
【robinwjb】: 试想一下,如果可以用非静态成员函数作为线程函数,如果没有定义一个这个类的实例, 岂不是无法调用线程函数了?
++++++++++++++++++++++++++++++++++++++++++++++++++++ 不明白呀!
------------------------------------------------------------ 静态成员(无论是函数还是变量)是存储在全局变量区的,也就是在整个程序生命中有效的。 而非静态成员是随类的实例生成而生,随着类的实例死亡而死的。 所以,如果非静态成员函数作为线程函数的话,此时这个类的实例不存在,而程序要生成线程了,却发现线程函数根本不存在。
【haoranisme】: 非静态成员函数,也存储全局变量区(堆区)吧?
【chehw】: 设某函数原型为LRESULTThreadProc(LPVOIDpv);
若为非静态成员函数,编译时自动展开为ThreadProc(pClass->this,pv);与线程函数调用不相符。所以必须使用全局函数或类静态成员函数
【haoranisme】: 会不会是为了区分代码段和数据段呢?
【robinwjb】: 非静态成员函数,也存储全局变量区(堆区)吧?
------------------------------------------------
如果没有类的实例,则非静态成员函数没有存储空间。 只是作为代码存在代码区
【wltg2001】: 成员函数都有一个隐含参数this,也就是指向这个对象实例的指针,所以不能做启动函数
【wltg2001】: 用成员函数作线程启动函数编译应该都不会过,就是因为参数不匹配的原因
【haoranisme】: 感觉不象
【kouzhongling】: 设某函数原型为LRESULTThreadProc(LPVOIDpv);
若为非静态成员函数,编译时自动展开为ThreadProc(pClass->this,pv);与线程函数调用不相符。所以必须使用全局函数或类静态成员函数
--------------------------------------------- 同意
作为线程入口当然不应该与类对象共存亡应该具有全局性 俺认为所有方法均在于代码段至于堆中是否存有可执行代码我也想知道 我一直认为堆只是存放数据的地方
【haoranisme】: 谢谢各位了!
【Nowish】: mark~ |
|
分享到:
相关推荐
VC启动一个新线程的三种方法,有需要的朋友可以参考下。 第一种AfxBeginThread() 用AfxBeginThread()函数来创建一个新线程来执行任务,工作者线程的AfxBeginThread的原型如下: CWinThread* AfxBeginThread(AFX_...
在MFC程序中创建一个线程,宜调用AfxBeginThread函数。该函数因参数不同而具有两种重载版本,分别对应工作者线程和用户接口(UI)线程。 工作者线程 CWinThread *AfxBeginThread( AFX_THREADPROC ...
在给定的代码中,使用了两个线程函数:CopyThread和ThreadProc。 2. 创建文件对象 创建文件对象,用于读取和写入文件。在C++中,可以使用CFile类或CreateFile函数创建文件对象。 3. 分配缓冲区 分配缓冲区,用于...
lpParameter:向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为NULL。 dwCreationFlags :线程标志,可取值如下 CREATE_SUSPENDED: 创建一个挂起的线程 0 :创建后立即激活。 ...
本文档对C++多线程编程进行了总结,介绍了三种创建线程的方法:CreateThread函数、AfxBeginThread函数和_beginthread()/_beginthreadex()函数,同时对线程的管理和终止进行了详细的讲解。 CreateThread函数 ...
创建一个线程过程数组,例如:DWORD WINAPI myThreadProcA(LPVOID p){DWORD dw =(DWORD)p; return dw;} DWORD WINAPI myThreadProcB(LPVOID p){DWORD dw =(DWORD)p; return dw * dw;}无效的CreateMyThreads...
* 使用 `ThreadProc` 函数作为线程函数 * 使用 `HANDLE` 变量来存储线程句柄 * 使用 `WaitForSingleObject` 函数来等待线程结束 第三部分:网络编程 * 使用 `send` 函数来发送数据 * 使用 `recv` 函数来接收数据 *...
windows线程之c++封装 class CThread { public: CThread(); virtual ~CThread(); // 启动线程 ... static DWORD ThreadProc(PVOID pArg); HANDLE m_ThreadHandle; DWORD m_ThreadId; };
在MFC程序中创建一个线程,宜调用AfxBeginThread函数。该函数因参数不同而具有两种重载版本,分别对应工作者线程和用户接口(UI)线程。 工作者线程 CWinThread *AfxBeginThread( AFX_THREADPROC ...
在我们实际编写的过程中,初学者并不知道我们的代码会编译在什么地方,这个时侯,我们可以在运行的时侯ALT + 8(VC中快捷键)反编译过来,一般有lea eax p、push offset p等取地址语句,这个时侯,我们大都需要以...
很多时候写windows程序都需要结合多线程,在C#中用如下得代码来创建并启动一个新的线程。 Thread thread = new Thread(new ThreadStart(ThreadProc));//实例化一个线程 thread.IsBackground = true;//将线程改为...
本文实例讲述了C++开启线程CreatThread函数的使用,实现主线程与工作线程交互的功能。分享给大家供大家参考。 具体实现代码如下: 代码如下://线程函数 DWORD WINAPI ThreadProc(LPVOID lpParameter) { for...
在多线程编程中,最简单的方法,无非就是利用 AfxBeginThread 来创建一个工作线程,看一下这个函数的说明: 代码如下: CWinThread* AFXAPI AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, int ...
本文实例讲述了C++设置事件通知线程工作的方法,其中主线程通过将事件状态设置为“受信”来通知工作线程工作。具体实现方法如下: 代码如下:// eventDemo.cpp : 定义控制台应用程序的入口点。 // #include ...
大华相机SDK单个相机显示的示例,主要使用MFC进行开发
易语言iocp传送文件源码,iocp传送文件,取类函数地址,取指针内容_整数,取变量地址_整数,CopyMemDword_1,CopyMemDword_2,启动,停止,取回数据,发送数据,断开连接,取回客户,取客户端口,取客户IP,取服务句柄,取标识,置...
易语言系统小工具源码,系统小工具,程序初始化,绘制_启动窗口,启动窗口_组件事件,枚举注册项,枚举,文件列表,CopyFile,取路径文件名,取路径扩展名,MsgProc,GetTextAddress,ThreadProc,Unicode转Ansi,字节数组转字节集,...
static CWinThread *CompilerThread = NULL; static HWND hwndThreadParent = NULL; static geBoolean ThreadActive = GE_FALSE; static HINSTANCE GBSPHandle = NULL; static GBSP_FuncHook *GlobalFHook; static ...
易语言TCP代理源码,TCP代理,启动代理服务,服务器,客户,关闭代理服务,取系统时间,取域名,取端口,取页面地址,Call,Start,Stop,ThreadProc,GetIndex,GetSocket,GetType,SetType,PostAcceptEx,PostWSARecv,PostWSASend,...
本文实例讲述了C++中Semaphore内核对象的用法,分享给大家供大家参考。具体方法如下: 代码如下:// Semaphore.cpp : 定义控制台应用程序的入口点。 // #include “stdafx.h” #include #include ...