Pure VS. Método Virtual ponteiro de função
-
20-08-2019 - |
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!
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.