从void*转换时的C++多态性问题

Mar*_*ant 0 c++ windows polymorphism inheritance multithreading

我有以下代码:

#include <windows.h>
#include <iostream>

static DWORD __stdcall startThread(void *);

class BaseClass {
private:

    void threadLoop() {
        // stuff ...
        std::cout << someStuff() << std::endl;
        // stuff ...
    }
protected:
    HANDLE handle;
    virtual int someStuff() {
        return 1;
    }
public:
    friend DWORD __stdcall startThread(void *);

    BaseClass() {
        handle = 0;
    };

    void start() {
        handle = CreateThread(NULL, 0, startThread, this, 0, NULL);
    }

    ~BaseClass() {
        if(handle != 0) {
            WaitForSingleObject(handle, INFINITE);
            CloseHandle(handle);
        }
    }
    // stuff
};

static DWORD __stdcall startThread(void *obj_) {
    BaseClass *obj = static_cast<BaseClass *>(obj_);

    obj->threadLoop();
    return 0;
}

class DerivedClass : public BaseClass {
public:
    virtual int someStuff() {
        return 2;
    };
};

int main() {
    BaseClass base;
    base.start();
    DerivedClass derived;
    derived.start();
}
Run Code Online (Sandbox Code Playgroud)

每个实例都使用WINAPI和辅助函数创建一个线程,该函数startThread将调用委托给threadLoop创建线程的对象的方法.现在问题是threadLoop调用另一个虚方法,但是如果我使用virual方法的其他实现创建派生类,则多态性似乎不起作用.

为什么?我怎样才能解决这个问题?

编辑:我更新了代码,因此线程不会在构造函数中启动.

Jam*_*nze 6

在构建派生对象之前,您将启动该线程.这是未定义的行为(因为您仍然可以在创建线程中执行代码时访问新线程中的对象).你必须分开构造和启动线程.

编辑:

处理此类问题的一种方法:

class Threadable
{
public:
    virtual Threadable() {}
    virtual run() = 0;
};

DWORD __stdcall startThread( void* object )
{
    static_cast<Threadable*>( object )->run();
}

class Thread
{
    std::auto_ptr<Threadable> myThread;
    HANDLE myHandle;
public:
    Thread( std::auto_ptr<Threadable> thread )
        : myThread( thread )
        , myHandle( CreateThread( NULL, 0, startThread, myThread.get(), 0, NULL ) )
    {
    }
    ~Thread()
    {
        if ( myHandle != NULL ) {
            WaitForSingleObject( myHandle, INFINITE );
            CloseHandle( myHandle );
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

然后得到你的,BaseClassDerivedClass从中 Threadable调用它们:

Thread base( std::auto_ptr<Threadable>( new BaseClass ) );
Thread derived( std::auto_ptr<Threadable>( new DerivedClass ) );
Run Code Online (Sandbox Code Playgroud)

这并不完美(我不喜欢在析构函数中或多或少地无限制等待),但它应该足以开始.(模拟上面代码中的任何拼写错误 - 我没有测试过它.)