Reinterpreta una funzione membro puntatore una 'buona idea'?
-
21-09-2019 - |
Domanda
Ho un thread di lavoro, che contiene un elenco di 'azioni' della discussione, e opera attraverso di loro come un momento.
template <class T> class ThreadAction
{
public:
typedef void (T::*action)();
ThreadAction(T* t, action f) :
func(f),obj(t) {}
void operator()() { (obj->*func)(); }
void (T::*func)();
T* obj;
};
E 'normalmente chiamato come questo
myActionThread->addAction(
new ThreadAction<TheirClass>(this, &TheirClass::enable)
);
Il che ha funzionato benissimo fino
void TheirClass::enable()
è stato cambiato in
bool TheirClass::enable()
Purtroppo non siamo in grado di cambiare di nuovo di nuovo perché altre cose ha bisogno del nuovo formato, (e sovraccarichi non possono differire in base al tipo di ritorno da solo).
ho provato
myActionThread->addAction(
new ThreadAction<TheirClass>(this,
reinterpret_cast<void(TheirClass::*)>(&TheirClass::enable)
)
);
che sembra funzionare bene, ma non sono certo che reinterpretando un puntatore a funzione come questo è 'definito' il comportamento, qualcuno può si prega di avvisare?
Soluzione
Questo è sicuramente non il comportamento sostenuto, e può potenzialmente causare il crash del programma.
In sostanza, è necessario fare un wrapper per TheirClass::enable()
che avrà il tipo di ritorno adeguato. Un semplice linea sarà sufficiente:
public:
void enableWrapper() { enable(); };
Quindi chiamare:
myActionThread->addAction(
new ThreadAction<TheirClass>(this, &TheirClass::enableWrapper)
);
Se non è possibile modificare direttamente TheirClass
, quindi creare una sottoclasse semplice o classe helper che implementa l'involucro.
Altri suggerimenti
Err, da quello che ho capito, si sta gettando da un metodo che restituisce un bool
ad un metodo che restituisce void
?
Questo può essere pericoloso, a seconda della chiamata / ritorno convenzione in uso. potrebbe dimenticare di pop il valore di ritorno -. O ignorare il valore di un registro con il valore di ritorno
Non è una buona idea. Considerare l'aggiunta di un parametro di modello supplementare per tipo di ritorno:
template <class T, typename RetType> class ThreadAction
{
public:
typedef RetType (T::*action)();
ThreadAction(T* t, action f) :
func(f),obj(t) {}
RetType operator()() { return (obj->*func)(); }
RetType (T::*func)();
T* obj;
};
Questa è un'applicazione di di ritorno void .
Trovo in generale che, quando la questione è del tipo "_______ è una buona idea?" la risposta è quasi sempre "NO!"
Questo è probabilmente vero senza contesto.