C++多态行为的不确定性

最近做一个项目,使用了一个抽象类的线程类,使用的时候发现有时会出现调用纯虚函数的情况,代码如下:

class Thread { public: Thread(int InitFlag=CREATE_SUSPENDED); ~Thread(); HANDLE m_ThreadHdl; private: virtual bool Execute()=0; static unsigned __stdcall threadPro( LPVOID pParam); }; Thread::Thread(int InitFlag) { m_ThreadHdl = (HANDLE)_beginthreadex(NULL,0,threadPro,this,InitFlag,0); } Thread::~Thread() { CloseHandle(m_ThreadHdl); } unsigned __stdcall Thread::threadPro( LPVOID pParam) { Thread* pThread=(Thread*)pParam; for (int i=0;i<5;i++) { pThread->Execute(); } return( 0 ); } class Thread1:public Thread { public: Thread1(int InitFlag=0):Thread(InitFlag) { }; private: virtual bool Execute() { cout<<"Thread1"<<endl; return true; }; }; class Thread2:public Thread { public: Thread2(int InitFlag=0):Thread(InitFlag) { }; private: virtual bool Execute() { cout<<"Thread2"<<endl; return true; }; }; int _tmain(int argc, _TCHAR* argv[]) { Thread1 th1; Thread2 th2; int a; cin>>a; }

运行时偶尔会出现如下情况:

C++多态行为的不确定性_第1张图片

 

后来把 Thread 的 Execute改了一下,改成:

virtual bool Execute() { cout<<"Thread base!"<<endl; return true; };

 

调试时发现偶尔出现下面这种情况:

 

 C++多态行为的不确定性_第2张图片

 

当我在抽象类线程函数里加Sleep(1000)后,就没有再发现这种情况了。我估计可能是动态联编有点延时。但加但我觉得也不是解决的办法。下面是我的解决办法:

 

class Thread { public: Thread(int InitFlag=CREATE_SUSPENDED); ~Thread(); HANDLE m_ThreadHdl; private: static bool m_bRunOnce; virtual bool Execute(); static unsigned __stdcall threadPro( LPVOID pParam); }; bool Thread::m_bRunOnce= true; Thread::Thread(int InitFlag) { m_ThreadHdl = (HANDLE)_beginthreadex(NULL,0,threadPro,this,InitFlag,0); } Thread::~Thread() { CloseHandle(m_ThreadHdl); } bool Thread::Execute() { Thread::m_bRunOnce = (!SGThread::m_bRunOnce); return true; } unsigned __stdcall Thread::threadPro( LPVOID pParam) { Thread* pThread=(Thread*)pParam; while(Thread::m_bRunOnce) { //如此虚函数没有执行,则下一语句设为false,退出 pThread->Execute(); Thread::m_bRunOnce = (!Thread::m_bRunOnce); } return( 0 ); } class Thread1:public Thread { public: Thread1(int InitFlag=0):Thread(InitFlag) { }; private: virtual bool Execute() { cout<<"Thread1"<<endl; return true; }; }; 

 

在《面向对象程序设计》中有讲:

虚函数与滞后联编
  多态性通过虚函数来实现,而虚函数的调用过程与滞后联编(或动态联编)密切相关,只有滞后联编才能实现多态性。也就是说,如果破坏了滞后联编,就不能调用虚函数,也就无法实现多态性。
  在下列情况下,可能会破坏虚函数的滞后联编环境:
  ①从前面的例子可以看出,为了使用滞后联编。必须通过指针或引用来调用虚函数。如果通过非指针或非引用类型的对象来调用虚函数,则不会有滞后联编的效果。在这种情况下.编译程序无法自动判别对象是否为其派生类的类型,而直接调用指定类的成员函数。
  ②当在程序中以作用域运算符来调用虚函数时,将破坏滞后联编。编译程序无需判别它是否是派生类中的成员函数,因为作用域运算符已明确地要求编译程序调用指定类的成员函数。
  ③当在基类的构造函数和析构函数中调用虚函数时。也会破坏滞后联编。例如。假定已定义了派生类的对象,由于派生类需要先调用基类的构造函数以进行初值设定。因此程序流程首先进入基类的构造函数;但是,此时派生类部分尚未定义完整,故在基类的构造函数下无法联编派生类中的虚函数,只能进行静态联编。

 

通过以上例子说明:多线程(或某种特别情况)环境下:会因为派生类生成的滞后,会破坏或影响虚函数的滞后联编环境。所以在使用虚函数动态联编时,函数行为具有不确定性,使用时需谨慎。可能是我知识有限,如有不当之处还请各位大侠批评指正。

你可能感兴趣的:(thread,多线程,C++,null,Class)