Recientemente encontré un gran ejemplo de por qué los moldes de estilo C son malos. Comenzamos con una clase siguiente implementar múltiples interfaces COM (tengo dos por razones de brevedad, pero no puede haber diez en la vida real):¿Qué duros ejemplos muestran que los moldes de estilo C son malos?
class CMyClassInitial : public IInterface1, public IInterface2 {
//declarations omitted
};
HRESULT CMyClassInitial::QueryInterface(REFIID iid, void** ppv)
{
if(ppv == 0) {
return E_POINTER;
}
*ppv = 0;
if(iid == __uuidof(IUnknown) || iid == __uuidof(IInterface1)) {
*ppv = (IInterface1*)this;
} else if(iid == __uuidof(IInterface2)) {
*ppv = (IInterface2*)this;
} else {
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
La implementación anterior utiliza C-moldes para adjusting pointers to account for multiple inheritance. Incluso funcionan como static_cast
s - this
el valor del puntero se ajustará correctamente.
Ahora copiar y pegar (o debería decir la reutilización de código de?) El mismo QueryInterface()
aplicación a alguna otra clase muy similar.
class CMyClassModified : public IInterface1 {
//declarations omitted
};
y deje la implementación de la misma. La nueva clase no hereda de IInterface2
más, pero
} else if(iid == __uuidof(IInterface2)) {
*ppv = (IInterface2*)this;
}
compilará bien y conversión de estilo C actuará como reinterpret_cast
- this
valor del puntero se copiará sin cambios. La persona que llama obtendrá un puntero a un objeto que en realidad no implementa IInterface2
- forma directa de comportamiento indefinido. Dichos problemas pueden ser difíciles de detectar en una gran base de datos y cuando hay muchas interfaces (no dos como en mi ejemplo).
Si se utilizó static_cast
que no habría sucedido - el compilador emitiría un error al intentar compilar
*ppv = static_cast<IInterface2*>(this);
OMI que es un ejemplo bastante duras de cómo el uso de moldes de tipo C pueden causar problemas graves.
¿Qué otros ejemplos hay?
Una gran gotcha, pero no estoy del todo seguro de que esto es adecuado para SO. Parece muy discutidor. En el mejor de los casos es una wiki comunitaria. – tenpn
@tenpn: No veo lo que se puede discutir aquí, solo un ejemplo de dispararse en la pierna en C++. – sharptooth
@sharptooth pero eso no es una pregunta, ¿verdad? – tenpn