Recentemente ho trovato il seguente pattern in un'API che sono stato forzato a utilizzare:
class SomeObject
{
public:
// Constructor.
SomeObject(bool copy = false);
// Set a value.
void SetValue(const ComplexType &value);
private:
bool m_copy;
ComplexType *m_pComplexType;
ComplexType m_complexType;
};
// ------------------------------------------------------------
SomeObject::SomeObject(bool copy) :
m_copy(copy)
{
}
// ------------------------------------------------------------
void SomeObject::SetValue(const ComplexType &value)
{
if (m_copy)
m_complexType.assign(value);
else
m_pComplexType = const_cast<ComplexType *>(&value);
}
Lo sfondo di questo pattern è che viene utilizzato per contenere i dati prima che vengano codificati e inviati a un socket TCP. La stranezza della copia è progettata per rendere efficiente la classe SomeObject
tenendo solo un puntatore all'oggetto finché non ha bisogno di essere codificato, ma fornisce anche l'opzione per copiare i valori se la durata del SomeObject
supera la durata di un ComplexType .
Tuttavia, considera quanto segue:
SomeObject SomeFunction()
{
ComplexType complexTypeInstance(1); // Create an instance of ComplexType.
SomeObject encodeHelper;
encodeHelper.SetValue(complexTypeInstance); // Okay.
return encodeHelper;
// Uh oh! complexTypeInstance has been destroyed, and
// now encoding will venture into the realm of undefined
// behaviour!
}
Sono inciampato su questo perché ho usato il costruttore di default, e questo ha comportato la codifica dei messaggi come vuoti (attraverso una combinazione di comportamento indefinito). Ci è voluta un'età assoluta per individuare la causa!
Ad ogni modo, questo è uno schema standard per qualcosa di simile? Ci sono dei vantaggi nel fare ciò in questo modo? Sovraccarico del metodo SetValue per accettare un puntatore che mi manca?
Grazie!