Pergunta

Recentemente eu estive projetando uma biblioteca de classe Thread, eu fiz uma classe abstrata da linha como o seguinte:

class Thread {
public:
    run() { /*start the thread*/ }
    kill() { /*stop the thread*/ }
protected:
    virtual int doOperation(unsigned int, void *) = 0;
};

aulas de rosca reais herdaria essa classe abstrata e implementar o método doOperation em sua própria lógica, algo semelhante ao Estratégia padrão .

O problema é que eu estou contando com uma biblioteca C-back-end que define a execução do segmento no seguinte função:

int startThread(char* name, (int)(*)(unsigned int, void*), int, int, int, void*);

Como você pode ver; o segundo parâmetro é uma função ponteiro para efectuar um ciclo de rosca (função principal), e aqui é o problema; desde que eu use esta função C para começar a rosca no método run, eu passar o endereço de doOperation para o segundo parâmetro, e isso não pode ser feito, por causa de incompatibilidade de tipo.

Eu tentei usar reinterpret_cast para retornar um ponteiro, mas proíbe I ISO-C ++ retornando um ponteiro de função membro inicializado-un. Eu não sei como superar este conflito, usando um método estático é a única solução que eu acho, mas ele explode meu padrão de design!

Foi útil?

Solução

Em primeiro lugar, certifique-se de ler o link Michael Burr fornecido, pois ele contém boas informações. Então, aqui é pseudo-código ish C ++ para isso:

int wrapperDoOperation(int v, void *ctx)
{
    Thread *thread = (Thread *)ctx;
    return thread->doOperation(v);
}

class Thread {
public:
    run() {
         startThread("bla", wrapperDoOperation, bla, bla, bla, (void *)this);
    }
    kill() { /*stop the thread*/ }
protected:
    virtual int doOperation(unsigned int) = 0;

friend wrapperDoOperation ......;
};

A idéia é que doOperation, sendo uma função membro de Thread, não precisa de um contexto void *, você pode apenas manter o que você deve passar como um contexto no próprio objeto. Portanto, você pode usar o ponteiro void para passar o actuall este ponteiro para o doOperation. Observe que os detalhes void * são ocultos dos usuários de sua classe, o que é bom.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top