Sei que isso foi perguntado tantas vezes e, por causa disso, é difícil cavar no meio do nada e encontrar um exemplo simples do que funciona.
Eu tenho isso, é simples e funciona para MyClass
...
#include <iostream>
using std::cout;
using std::endl;
class MyClass
{
public:
MyClass();
static void Callback(MyClass* instance, int x);
private:
int private_x;
};
class EventHandler
{
public:
void addHandler(MyClass* owner)
{
cout << "Handler added..." << endl;
//Let's pretend an event just occured
owner->Callback(owner,1);
}
};
EventHandler* handler;
MyClass::MyClass()
{
private_x = 5;
handler->addHandler(this);
}
void MyClass::Callback(MyClass* instance, int x)
{
cout << x + instance->private_x << endl;
}
int main(int argc, char** argv)
{
handler = new EventHandler();
MyClass* myClass = new MyClass();
}
class YourClass
{
public:
YourClass();
static void Callback(YourClass* instance, int x);
};
Como isso pode ser reescrito para EventHandler::addHandler()
que funcione com MyClass
e YourClass
. Sinto muito, mas é apenas a maneira como meu cérebro funciona. Preciso ver um exemplo simples do que funciona antes de compreender por que / como funciona. Se você tem uma maneira favorita de fazer isso funcionar, agora é a hora de exibi-la, marque esse código e poste-o de volta.
[editar]
Ele foi respondido, mas a resposta foi excluída antes que eu pudesse marcar. A resposta no meu caso foi uma função modelada. AddHandler alterado para ...
class EventHandler
{
public:
template<typename T>
void addHandler(T* owner)
{
cout << "Handler added..." << endl;
//Let's pretend an event just occured
owner->Callback(owner,1);
}
};
Respostas:
Em vez de ter métodos estáticos e passar um ponteiro para a instância da classe, você pode usar a funcionalidade no novo padrão C ++ 11:
std::function
estd::bind
:O
addHandler
método agora aceita umstd::function
argumento e este "objeto de função" não tem valor de retorno e leva um inteiro como argumento.Para vinculá-lo a uma função específica, você usa
std::bind
:Você precisa usar
std::bind
ao adicionar o manipulador, pois você precisa especificar explicitamente othis
ponteiro implícito como um argumento. Se você tem uma função independente, não precisa usarstd::bind
:O fato de o manipulador de eventos usar
std::function
objetos também torna possível usar as novas funções lambda do C ++ 11 :fonte
std::bind
apenas retorna um objeto (não especificado) e, quando terminar, pode simplesmente deixá-lo sair do escopo. Se o objeto vinculado for destruído e você tentar chamar a função, obterá um comportamento indefinido .handler->addHandler()
, significa que em algum lugar você cria um objetoEventHandler
? Boa resposta aliás, +1....., _1, _2)
e assim por diante.Esta é uma versão concisa que funciona com retornos de chamada de método de classe e com retornos de chamada de função regulares. Neste exemplo, para mostrar como os parâmetros são tratados, a função de retorno de chamada usa dois parâmetros:
bool
eint
.Isso restringe o código específico do C ++ 11 ao método addCallback e aos dados privados na classe Caller. Para mim, pelo menos, isso minimiza a chance de cometer erros na implementação.
fonte
O que você quer fazer é fazer uma interface que lida com esse código e todas as suas classes implementam a interface.
Observe que, para que isso funcione, a função "Callback" não é estática, o que acredito ser uma melhoria. Se você quiser que seja estático, você precisa fazer isso como o JaredC sugere com modelos.
fonte
Um exemplo funcional completo do código acima ... para C ++ 11:
A saída deve ser:
fonte
MyClass
eYourClass
ambos podem ser derivados deSomeonesClass
umCallback
método abstrato (virtual) . SeuaddHandler
aceitaria objetos do tipoSomeonesClass
eMyClass
eYourClass
pode substituirCallback
a fornecer sua implementação específica do comportamento de retorno de chamada.fonte
Se você tiver retornos de chamada com parâmetros diferentes, poderá usar os modelos da seguinte maneira:
// compilar com: g ++ -std = c ++ 11 myTemplatedCPPcallbacks.cpp -o myTemplatedCPPcallbacksApp
fonte
YourClass
. Você parece ter removido aquela classe e adicionado uma diferenteOtherClass
. Além disso, a pergunta já teve uma resposta bem recebida. Até que ponto a sua solução é melhor para que valha a pena postar?